Support copying multiple array layers in one B2T and T2B copy command
This patch adds the support of copying with multiple texture array layers in one buffer-to-texture and texture-to-buffer copy command. BUG=dawn:453 TEST=dawn_end2end_tests Change-Id: If009dbb29f2b0ef0667715eed0d66053b1491fd4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23248 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
parent
250f26229b
commit
92379bff49
|
@ -44,8 +44,8 @@ namespace dawn_native {
|
||||||
const uint32_t mipLevel) {
|
const uint32_t mipLevel) {
|
||||||
Extent3D extent = texture->GetMipLevelPhysicalSize(mipLevel);
|
Extent3D extent = texture->GetMipLevelPhysicalSize(mipLevel);
|
||||||
|
|
||||||
if (extent.depth == copySize.depth && extent.width == copySize.width &&
|
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
extent.height == copySize.height) {
|
if (extent.width == copySize.width && extent.height == copySize.height) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -577,41 +577,59 @@ namespace dawn_native { namespace d3d12 {
|
||||||
Texture* texture = ToBackend(copy->destination.texture.Get());
|
Texture* texture = ToBackend(copy->destination.texture.Get());
|
||||||
|
|
||||||
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
ASSERT(copy->copySize.depth == 1);
|
// TODO(jiawei.shao@intel.com): use copy->destination.origin.z instead of
|
||||||
SubresourceRange subresource = SubresourceRange::SingleSubresource(
|
// copy->destination.arrayLayer once GPUTextureCopyView.arrayLayer to
|
||||||
copy->destination.mipLevel, copy->destination.arrayLayer);
|
// GPUTextureCopyView.origin.z is done.
|
||||||
|
SubresourceRange subresources = {copy->destination.mipLevel, 1,
|
||||||
|
copy->destination.arrayLayer,
|
||||||
|
copy->copySize.depth};
|
||||||
if (IsCompleteSubresourceCopiedTo(texture, copy->copySize,
|
if (IsCompleteSubresourceCopiedTo(texture, copy->copySize,
|
||||||
copy->destination.mipLevel)) {
|
copy->destination.mipLevel)) {
|
||||||
texture->SetIsSubresourceContentInitialized(true, subresource);
|
texture->SetIsSubresourceContentInitialized(true, subresources);
|
||||||
} else {
|
} else {
|
||||||
texture->EnsureSubresourceContentInitialized(commandContext, subresource);
|
texture->EnsureSubresourceContentInitialized(commandContext, subresources);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopySrc);
|
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopySrc);
|
||||||
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopyDst,
|
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopyDst,
|
||||||
subresource);
|
subresources);
|
||||||
|
|
||||||
auto copySplit = ComputeTextureCopySplit(
|
const uint64_t bytesPerSlice =
|
||||||
copy->destination.origin, copy->copySize, texture->GetFormat(),
|
copy->source.bytesPerRow * copy->source.rowsPerImage;
|
||||||
copy->source.offset, copy->source.bytesPerRow, copy->source.rowsPerImage);
|
|
||||||
|
|
||||||
D3D12_TEXTURE_COPY_LOCATION textureLocation =
|
const dawn_native::Extent3D copyOneLayerSize = {copy->copySize.width,
|
||||||
ComputeTextureCopyLocationForTexture(texture, copy->destination.mipLevel,
|
copy->copySize.height, 1};
|
||||||
copy->destination.arrayLayer);
|
uint64_t bufferOffsetForNextSlice = 0;
|
||||||
|
for (uint32_t copySlice = copy->destination.arrayLayer;
|
||||||
|
copySlice < copy->destination.arrayLayer + copy->copySize.depth;
|
||||||
|
++copySlice) {
|
||||||
|
// TODO(jiawei.shao@intel.com): compute copySplit once for all texture array
|
||||||
|
// layers when possible.
|
||||||
|
auto copySplit = ComputeTextureCopySplit(
|
||||||
|
copy->destination.origin, copyOneLayerSize, texture->GetFormat(),
|
||||||
|
bufferOffsetForNextSlice + copy->source.offset,
|
||||||
|
copy->source.bytesPerRow, copy->source.rowsPerImage);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
D3D12_TEXTURE_COPY_LOCATION textureLocation =
|
||||||
TextureCopySplit::CopyInfo& info = copySplit.copies[i];
|
ComputeTextureCopyLocationForTexture(
|
||||||
|
texture, copy->destination.mipLevel, copySlice);
|
||||||
|
|
||||||
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
|
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
||||||
ComputeBufferLocationForCopyTextureRegion(
|
const TextureCopySplit::CopyInfo& info = copySplit.copies[i];
|
||||||
texture, buffer->GetD3D12Resource().Get(), info.bufferSize,
|
|
||||||
copySplit.offset, copy->source.bytesPerRow);
|
|
||||||
D3D12_BOX sourceRegion =
|
|
||||||
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
|
|
||||||
|
|
||||||
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
|
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
|
||||||
info.textureOffset.y, info.textureOffset.z,
|
ComputeBufferLocationForCopyTextureRegion(
|
||||||
&bufferLocation, &sourceRegion);
|
texture, buffer->GetD3D12Resource().Get(), info.bufferSize,
|
||||||
|
copySplit.offset, copy->source.bytesPerRow);
|
||||||
|
D3D12_BOX sourceRegion =
|
||||||
|
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
|
||||||
|
|
||||||
|
commandList->CopyTextureRegion(
|
||||||
|
&textureLocation, info.textureOffset.x, info.textureOffset.y,
|
||||||
|
info.textureOffset.z, &bufferLocation, &sourceRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferOffsetForNextSlice += bytesPerSlice;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -622,38 +640,53 @@ namespace dawn_native { namespace d3d12 {
|
||||||
Buffer* buffer = ToBackend(copy->destination.buffer.Get());
|
Buffer* buffer = ToBackend(copy->destination.buffer.Get());
|
||||||
|
|
||||||
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
ASSERT(copy->copySize.depth == 1);
|
// TODO(jiawei.shao@intel.com): use copy->destination.origin.z instead of
|
||||||
SubresourceRange subresource = SubresourceRange::SingleSubresource(
|
// copy->destination.arrayLayer once GPUTextureCopyView.arrayLayer to
|
||||||
copy->source.mipLevel, copy->source.arrayLayer);
|
// GPUTextureCopyView.origin.z is done.
|
||||||
texture->EnsureSubresourceContentInitialized(commandContext, subresource);
|
SubresourceRange subresources = {copy->source.mipLevel, 1,
|
||||||
|
copy->source.arrayLayer, copy->copySize.depth};
|
||||||
|
texture->EnsureSubresourceContentInitialized(commandContext, subresources);
|
||||||
|
|
||||||
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopySrc,
|
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopySrc,
|
||||||
subresource);
|
subresources);
|
||||||
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
|
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
|
||||||
|
|
||||||
TextureCopySplit copySplit = ComputeTextureCopySplit(
|
const uint64_t bytesPerSlice =
|
||||||
copy->source.origin, copy->copySize, texture->GetFormat(),
|
copy->destination.bytesPerRow * copy->destination.rowsPerImage;
|
||||||
copy->destination.offset, copy->destination.bytesPerRow,
|
|
||||||
copy->destination.rowsPerImage);
|
|
||||||
|
|
||||||
D3D12_TEXTURE_COPY_LOCATION textureLocation =
|
const dawn_native::Extent3D copyOneLayerSize = {copy->copySize.width,
|
||||||
ComputeTextureCopyLocationForTexture(texture, copy->source.mipLevel,
|
copy->copySize.height, 1};
|
||||||
copy->source.arrayLayer);
|
uint64_t bufferOffsetForNextSlice = 0;
|
||||||
|
for (uint32_t copySlice = copy->source.arrayLayer;
|
||||||
|
copySlice < copy->source.arrayLayer + copy->copySize.depth; ++copySlice) {
|
||||||
|
// TODO(jiawei.shao@intel.com): compute copySplit once for all texture array
|
||||||
|
// layers when possible.
|
||||||
|
TextureCopySplit copySplit = ComputeTextureCopySplit(
|
||||||
|
copy->source.origin, copyOneLayerSize, texture->GetFormat(),
|
||||||
|
bufferOffsetForNextSlice + copy->destination.offset,
|
||||||
|
copy->destination.bytesPerRow, copy->destination.rowsPerImage);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
D3D12_TEXTURE_COPY_LOCATION textureLocation =
|
||||||
TextureCopySplit::CopyInfo& info = copySplit.copies[i];
|
ComputeTextureCopyLocationForTexture(texture, copy->source.mipLevel,
|
||||||
|
copySlice);
|
||||||
|
|
||||||
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
|
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
||||||
ComputeBufferLocationForCopyTextureRegion(
|
const TextureCopySplit::CopyInfo& info = copySplit.copies[i];
|
||||||
texture, buffer->GetD3D12Resource().Get(), info.bufferSize,
|
|
||||||
copySplit.offset, copy->destination.bytesPerRow);
|
|
||||||
|
|
||||||
D3D12_BOX sourceRegion =
|
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
|
||||||
ComputeD3D12BoxFromOffsetAndSize(info.textureOffset, info.copySize);
|
ComputeBufferLocationForCopyTextureRegion(
|
||||||
|
texture, buffer->GetD3D12Resource().Get(), info.bufferSize,
|
||||||
|
copySplit.offset, copy->destination.bytesPerRow);
|
||||||
|
|
||||||
commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
|
D3D12_BOX sourceRegion =
|
||||||
info.bufferOffset.y, info.bufferOffset.z,
|
ComputeD3D12BoxFromOffsetAndSize(info.textureOffset, info.copySize);
|
||||||
&textureLocation, &sourceRegion);
|
|
||||||
|
commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
|
||||||
|
info.bufferOffset.y, info.bufferOffset.z,
|
||||||
|
&textureLocation, &sourceRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferOffsetForNextSlice += bytesPerSlice;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -748,22 +748,40 @@ namespace dawn_native { namespace metal {
|
||||||
EnsureDestinationTextureInitialized(texture, copy->copySize, copy->destination);
|
EnsureDestinationTextureInitialized(texture, copy->copySize, copy->destination);
|
||||||
|
|
||||||
Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(dst.mipLevel);
|
Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(dst.mipLevel);
|
||||||
TextureBufferCopySplit splittedCopies = ComputeTextureBufferCopySplit(
|
|
||||||
dst.origin, copySize, texture->GetFormat(), virtualSizeAtLevel,
|
|
||||||
buffer->GetSize(), src.offset, src.bytesPerRow, src.rowsPerImage);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < splittedCopies.count; ++i) {
|
uint64_t bufferOffsetForNextSlice = 0;
|
||||||
const TextureBufferCopySplit::CopyInfo& copyInfo = splittedCopies.copies[i];
|
const uint64_t bytesPerSlice = src.bytesPerRow * src.rowsPerImage;
|
||||||
[commandContext->EnsureBlit() copyFromBuffer:buffer->GetMTLBuffer()
|
|
||||||
sourceOffset:copyInfo.bufferOffset
|
const dawn_native::Extent3D copyOneLayerSize = {copySize.width, copySize.height,
|
||||||
sourceBytesPerRow:copyInfo.bytesPerRow
|
1};
|
||||||
sourceBytesPerImage:copyInfo.bytesPerImage
|
// TODO(jiawei.shao@intel.com): use dst.origin.z instead of dst.arrayLayer once
|
||||||
sourceSize:copyInfo.copyExtent
|
// GPUTextureCopyView.arrayLayer to GPUTextureCopyView.origin.z is done.
|
||||||
toTexture:texture->GetMTLTexture()
|
for (uint32_t copySlice = dst.arrayLayer;
|
||||||
destinationSlice:dst.arrayLayer
|
copySlice < dst.arrayLayer + copySize.depth; ++copySlice) {
|
||||||
destinationLevel:dst.mipLevel
|
// TODO(jiawei.shao@intel.com): compute splitCopies once for all texture
|
||||||
destinationOrigin:copyInfo.textureOrigin];
|
// array layers when possible.
|
||||||
|
TextureBufferCopySplit splitCopies = ComputeTextureBufferCopySplit(
|
||||||
|
dst.origin, copyOneLayerSize, texture->GetFormat(), virtualSizeAtLevel,
|
||||||
|
buffer->GetSize(), bufferOffsetForNextSlice + src.offset,
|
||||||
|
src.bytesPerRow, src.rowsPerImage);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < splitCopies.count; ++i) {
|
||||||
|
const TextureBufferCopySplit::CopyInfo& copyInfo =
|
||||||
|
splitCopies.copies[i];
|
||||||
|
[commandContext->EnsureBlit() copyFromBuffer:buffer->GetMTLBuffer()
|
||||||
|
sourceOffset:copyInfo.bufferOffset
|
||||||
|
sourceBytesPerRow:copyInfo.bytesPerRow
|
||||||
|
sourceBytesPerImage:copyInfo.bytesPerImage
|
||||||
|
sourceSize:copyInfo.copyExtent
|
||||||
|
toTexture:texture->GetMTLTexture()
|
||||||
|
destinationSlice:copySlice
|
||||||
|
destinationLevel:dst.mipLevel
|
||||||
|
destinationOrigin:copyInfo.textureOrigin];
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferOffsetForNextSlice += bytesPerSlice;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,21 +796,37 @@ namespace dawn_native { namespace metal {
|
||||||
EnsureSourceTextureInitialized(texture, copy->copySize, copy->source);
|
EnsureSourceTextureInitialized(texture, copy->copySize, copy->source);
|
||||||
|
|
||||||
Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(src.mipLevel);
|
Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(src.mipLevel);
|
||||||
TextureBufferCopySplit splittedCopies = ComputeTextureBufferCopySplit(
|
|
||||||
src.origin, copySize, texture->GetFormat(), virtualSizeAtLevel,
|
|
||||||
buffer->GetSize(), dst.offset, dst.bytesPerRow, dst.rowsPerImage);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < splittedCopies.count; ++i) {
|
uint64_t bufferOffsetForNextSlice = 0;
|
||||||
const TextureBufferCopySplit::CopyInfo& copyInfo = splittedCopies.copies[i];
|
const uint64_t bytesPerSlice = dst.bytesPerRow * dst.rowsPerImage;
|
||||||
[commandContext->EnsureBlit() copyFromTexture:texture->GetMTLTexture()
|
|
||||||
sourceSlice:src.arrayLayer
|
const dawn_native::Extent3D copyOneLayerSize = {copySize.width, copySize.height,
|
||||||
sourceLevel:src.mipLevel
|
1};
|
||||||
sourceOrigin:copyInfo.textureOrigin
|
// TODO(jiawei.shao@intel.com): use src.origin.z instead of src.arrayLayer once
|
||||||
sourceSize:copyInfo.copyExtent
|
// GPUTextureCopyView.arrayLayer to GPUTextureCopyView.origin.z is done.
|
||||||
toBuffer:buffer->GetMTLBuffer()
|
for (uint32_t copySlice = src.arrayLayer;
|
||||||
destinationOffset:copyInfo.bufferOffset
|
copySlice < src.arrayLayer + copySize.depth; ++copySlice) {
|
||||||
destinationBytesPerRow:copyInfo.bytesPerRow
|
// TODO(jiawei.shao@intel.com): compute splitCopies once for all texture
|
||||||
destinationBytesPerImage:copyInfo.bytesPerImage];
|
// array layers when possible.
|
||||||
|
TextureBufferCopySplit splitCopies = ComputeTextureBufferCopySplit(
|
||||||
|
src.origin, copyOneLayerSize, texture->GetFormat(), virtualSizeAtLevel,
|
||||||
|
buffer->GetSize(), bufferOffsetForNextSlice + dst.offset,
|
||||||
|
dst.bytesPerRow, dst.rowsPerImage);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < splitCopies.count; ++i) {
|
||||||
|
const TextureBufferCopySplit::CopyInfo& copyInfo =
|
||||||
|
splitCopies.copies[i];
|
||||||
|
[commandContext->EnsureBlit() copyFromTexture:texture->GetMTLTexture()
|
||||||
|
sourceSlice:copySlice
|
||||||
|
sourceLevel:src.mipLevel
|
||||||
|
sourceOrigin:copyInfo.textureOrigin
|
||||||
|
sourceSize:copyInfo.copyExtent
|
||||||
|
toBuffer:buffer->GetMTLBuffer()
|
||||||
|
destinationOffset:copyInfo.bufferOffset
|
||||||
|
destinationBytesPerRow:copyInfo.bytesPerRow
|
||||||
|
destinationBytesPerImage:copyInfo.bytesPerImage];
|
||||||
|
}
|
||||||
|
bufferOffsetForNextSlice += bytesPerSlice;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -515,13 +515,15 @@ namespace dawn_native { namespace opengl {
|
||||||
const GLFormat& format = texture->GetGLFormat();
|
const GLFormat& format = texture->GetGLFormat();
|
||||||
|
|
||||||
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
ASSERT(copy->copySize.depth == 1);
|
// TODO(jiawei.shao@intel.com): use copy->destination.origin.z instead of
|
||||||
SubresourceRange subresource =
|
// copy->destination.arrayLayer once GPUTextureCopyView.arrayLayer to
|
||||||
SubresourceRange::SingleSubresource(dst.mipLevel, dst.arrayLayer);
|
// GPUTextureCopyView.origin.z is done.
|
||||||
|
SubresourceRange subresources = {dst.mipLevel, 1, dst.arrayLayer,
|
||||||
|
copy->copySize.depth};
|
||||||
if (IsCompleteSubresourceCopiedTo(texture, copySize, dst.mipLevel)) {
|
if (IsCompleteSubresourceCopiedTo(texture, copySize, dst.mipLevel)) {
|
||||||
texture->SetIsSubresourceContentInitialized(true, subresource);
|
texture->SetIsSubresourceContentInitialized(true, subresources);
|
||||||
} else {
|
} else {
|
||||||
texture->EnsureSubresourceContentInitialized(subresource);
|
texture->EnsureSubresourceContentInitialized(subresources);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->GetHandle());
|
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->GetHandle());
|
||||||
|
@ -549,8 +551,8 @@ namespace dawn_native { namespace opengl {
|
||||||
if (texture->GetArrayLayers() > 1) {
|
if (texture->GetArrayLayers() > 1) {
|
||||||
gl.CompressedTexSubImage3D(
|
gl.CompressedTexSubImage3D(
|
||||||
target, dst.mipLevel, dst.origin.x, dst.origin.y, dst.arrayLayer,
|
target, dst.mipLevel, dst.origin.x, dst.origin.y, dst.arrayLayer,
|
||||||
copyExtent.width, copyExtent.height, 1, format.internalFormat,
|
copyExtent.width, copyExtent.height, copyExtent.depth,
|
||||||
copyDataSize,
|
format.internalFormat, copyDataSize,
|
||||||
reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
|
reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
|
||||||
} else {
|
} else {
|
||||||
gl.CompressedTexSubImage2D(
|
gl.CompressedTexSubImage2D(
|
||||||
|
@ -564,7 +566,8 @@ namespace dawn_native { namespace opengl {
|
||||||
if (texture->GetArrayLayers() > 1) {
|
if (texture->GetArrayLayers() > 1) {
|
||||||
gl.TexSubImage3D(target, dst.mipLevel, dst.origin.x,
|
gl.TexSubImage3D(target, dst.mipLevel, dst.origin.x,
|
||||||
dst.origin.y, dst.arrayLayer, copySize.width,
|
dst.origin.y, dst.arrayLayer, copySize.width,
|
||||||
copySize.height, 1, format.format, format.type,
|
copySize.height, copySize.depth, format.format,
|
||||||
|
format.type,
|
||||||
reinterpret_cast<void*>(
|
reinterpret_cast<void*>(
|
||||||
static_cast<uintptr_t>(src.offset)));
|
static_cast<uintptr_t>(src.offset)));
|
||||||
} else {
|
} else {
|
||||||
|
@ -606,9 +609,9 @@ namespace dawn_native { namespace opengl {
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
ASSERT(copy->copySize.depth == 1);
|
SubresourceRange subresources = {src.mipLevel, 1, src.arrayLayer,
|
||||||
texture->EnsureSubresourceContentInitialized(
|
copy->copySize.depth};
|
||||||
SubresourceRange::SingleSubresource(src.mipLevel, src.arrayLayer));
|
texture->EnsureSubresourceContentInitialized(subresources);
|
||||||
// The only way to move data from a texture to a buffer in GL is via
|
// The only way to move data from a texture to a buffer in GL is via
|
||||||
// glReadPixels with a pack buffer. Create a temporary FBO for the copy.
|
// glReadPixels with a pack buffer. Create a temporary FBO for the copy.
|
||||||
gl.BindTexture(target, texture->GetHandle());
|
gl.BindTexture(target, texture->GetHandle());
|
||||||
|
@ -636,29 +639,42 @@ namespace dawn_native { namespace opengl {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
|
||||||
|
gl.PixelStorei(GL_PACK_ROW_LENGTH, dst.bytesPerRow / format.blockByteSize);
|
||||||
|
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.rowsPerImage);
|
||||||
|
|
||||||
|
uint8_t* offset =
|
||||||
|
reinterpret_cast<uint8_t*>(static_cast<uintptr_t>(dst.offset));
|
||||||
switch (texture->GetDimension()) {
|
switch (texture->GetDimension()) {
|
||||||
case wgpu::TextureDimension::e2D:
|
case wgpu::TextureDimension::e2D: {
|
||||||
if (texture->GetArrayLayers() > 1) {
|
if (texture->GetArrayLayers() == 1) {
|
||||||
gl.FramebufferTextureLayer(GL_READ_FRAMEBUFFER, glAttachment,
|
|
||||||
texture->GetHandle(), src.mipLevel,
|
|
||||||
src.arrayLayer);
|
|
||||||
} else {
|
|
||||||
gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment, target,
|
gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment, target,
|
||||||
texture->GetHandle(), src.mipLevel);
|
texture->GetHandle(), src.mipLevel);
|
||||||
|
gl.ReadPixels(src.origin.x, src.origin.y, copySize.width,
|
||||||
|
copySize.height, glFormat.format, glFormat.type,
|
||||||
|
offset);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint64_t bytesPerImage = dst.bytesPerRow * dst.rowsPerImage;
|
||||||
|
for (uint32_t layer = 0; layer < copySize.depth; ++layer) {
|
||||||
|
gl.FramebufferTextureLayer(GL_READ_FRAMEBUFFER, glAttachment,
|
||||||
|
texture->GetHandle(), src.mipLevel,
|
||||||
|
src.arrayLayer + layer);
|
||||||
|
gl.ReadPixels(src.origin.x, src.origin.y, copySize.width,
|
||||||
|
copySize.height, glFormat.format, glFormat.type,
|
||||||
|
offset);
|
||||||
|
|
||||||
|
offset += bytesPerImage;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
|
|
||||||
gl.PixelStorei(GL_PACK_ROW_LENGTH, dst.bytesPerRow / format.blockByteSize);
|
|
||||||
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.rowsPerImage);
|
|
||||||
ASSERT(copySize.depth == 1 && src.origin.z == 0);
|
|
||||||
void* offset = reinterpret_cast<void*>(static_cast<uintptr_t>(dst.offset));
|
|
||||||
gl.ReadPixels(src.origin.x, src.origin.y, copySize.width, copySize.height,
|
|
||||||
glFormat.format, glFormat.type, offset);
|
|
||||||
gl.PixelStorei(GL_PACK_ROW_LENGTH, 0);
|
gl.PixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||||
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
|
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
|
||||||
|
|
||||||
|
|
|
@ -448,9 +448,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
VkImageSubresourceLayers subresource = region.imageSubresource;
|
VkImageSubresourceLayers subresource = region.imageSubresource;
|
||||||
|
|
||||||
ASSERT(dst.texture->GetDimension() == wgpu::TextureDimension::e2D);
|
ASSERT(dst.texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
ASSERT(copy->copySize.depth == 1);
|
SubresourceRange range = {subresource.mipLevel, 1, subresource.baseArrayLayer,
|
||||||
SubresourceRange range = SubresourceRange::SingleSubresource(
|
subresource.layerCount};
|
||||||
subresource.mipLevel, subresource.baseArrayLayer);
|
|
||||||
if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize,
|
if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize,
|
||||||
subresource.mipLevel)) {
|
subresource.mipLevel)) {
|
||||||
// Since texture has been overwritten, it has been "initialized"
|
// Since texture has been overwritten, it has been "initialized"
|
||||||
|
@ -484,9 +483,9 @@ namespace dawn_native { namespace vulkan {
|
||||||
VkImageSubresourceLayers subresource = region.imageSubresource;
|
VkImageSubresourceLayers subresource = region.imageSubresource;
|
||||||
|
|
||||||
ASSERT(src.texture->GetDimension() == wgpu::TextureDimension::e2D);
|
ASSERT(src.texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
ASSERT(copy->copySize.depth == 1);
|
const SubresourceRange range = {subresource.mipLevel, 1,
|
||||||
SubresourceRange range = SubresourceRange::SingleSubresource(
|
subresource.baseArrayLayer,
|
||||||
subresource.mipLevel, subresource.baseArrayLayer);
|
subresource.layerCount};
|
||||||
ToBackend(src.texture)
|
ToBackend(src.texture)
|
||||||
->EnsureSubresourceContentInitialized(recordingContext, range);
|
->EnsureSubresourceContentInitialized(recordingContext, range);
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,6 @@ namespace dawn_native { namespace vulkan {
|
||||||
region.imageSubresource.aspectMask = texture->GetVkAspectMask();
|
region.imageSubresource.aspectMask = texture->GetVkAspectMask();
|
||||||
region.imageSubresource.mipLevel = textureCopy.mipLevel;
|
region.imageSubresource.mipLevel = textureCopy.mipLevel;
|
||||||
region.imageSubresource.baseArrayLayer = textureCopy.arrayLayer;
|
region.imageSubresource.baseArrayLayer = textureCopy.arrayLayer;
|
||||||
region.imageSubresource.layerCount = 1;
|
|
||||||
|
|
||||||
region.imageOffset.x = textureCopy.origin.x;
|
region.imageOffset.x = textureCopy.origin.x;
|
||||||
region.imageOffset.y = textureCopy.origin.y;
|
region.imageOffset.y = textureCopy.origin.y;
|
||||||
|
@ -91,7 +90,10 @@ namespace dawn_native { namespace vulkan {
|
||||||
Extent3D imageExtent = ComputeTextureCopyExtent(textureCopy, copySize);
|
Extent3D imageExtent = ComputeTextureCopyExtent(textureCopy, copySize);
|
||||||
region.imageExtent.width = imageExtent.width;
|
region.imageExtent.width = imageExtent.width;
|
||||||
region.imageExtent.height = imageExtent.height;
|
region.imageExtent.height = imageExtent.height;
|
||||||
region.imageExtent.depth = copySize.depth;
|
|
||||||
|
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
|
region.imageSubresource.layerCount = copySize.depth;
|
||||||
|
region.imageExtent.depth = 1;
|
||||||
|
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ class CopyTests : public DawnTest {
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint32_t bytesPerRow;
|
uint32_t bytesPerRow;
|
||||||
|
uint32_t rowsPerImage;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<RGBA8> GetExpectedTextureData(
|
static std::vector<RGBA8> GetExpectedTextureData(
|
||||||
|
@ -56,12 +57,14 @@ class CopyTests : public DawnTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
static BufferSpec MinimumBufferSpec(uint32_t width,
|
static BufferSpec MinimumBufferSpec(uint32_t width,
|
||||||
uint32_t height,
|
uint32_t rowsPerImage,
|
||||||
uint32_t arrayLayer = 1) {
|
uint32_t arrayLayer = 1,
|
||||||
|
bool testZeroRowsPerImage = true) {
|
||||||
const uint32_t bytesPerRow = utils::GetMinimumBytesPerRow(kTextureFormat, width);
|
const uint32_t bytesPerRow = utils::GetMinimumBytesPerRow(kTextureFormat, width);
|
||||||
const uint32_t totalBufferSize = utils::GetBytesInBufferTextureCopy(
|
const uint32_t totalBufferSize = utils::GetBytesInBufferTextureCopy(
|
||||||
kTextureFormat, width, bytesPerRow, height, arrayLayer);
|
kTextureFormat, width, bytesPerRow, rowsPerImage, arrayLayer);
|
||||||
return {totalBufferSize, 0, bytesPerRow};
|
uint32_t appliedRowsPerImage = testZeroRowsPerImage ? 0 : rowsPerImage;
|
||||||
|
return {totalBufferSize, 0, bytesPerRow, appliedRowsPerImage};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PackTextureData(const RGBA8* srcData, uint32_t width, uint32_t height, uint32_t srcTexelsPerRow, RGBA8* dstData, uint32_t dstTexelsPerRow) {
|
static void PackTextureData(const RGBA8* srcData, uint32_t width, uint32_t height, uint32_t srcTexelsPerRow, RGBA8* dstData, uint32_t dstTexelsPerRow) {
|
||||||
|
@ -90,30 +93,24 @@ class CopyTests_T2B : public CopyTests {
|
||||||
descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc;
|
descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc;
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||||
|
|
||||||
const uint32_t rowsPerImage = textureSpec.textureSize.height >> textureSpec.level;
|
|
||||||
const utils::BufferTextureCopyLayout copyLayout =
|
const utils::BufferTextureCopyLayout copyLayout =
|
||||||
utils::GetBufferTextureCopyLayoutForTexture2DAtLevel(
|
utils::GetBufferTextureCopyLayoutForTexture2DAtLevel(
|
||||||
kTextureFormat, textureSpec.textureSize, textureSpec.level, rowsPerImage);
|
kTextureFormat, textureSpec.textureSize, textureSpec.level,
|
||||||
|
bufferSpec.rowsPerImage);
|
||||||
|
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
|
||||||
// Initialize the source texture
|
// Initialize the source texture
|
||||||
std::vector<RGBA8> textureArrayData = GetExpectedTextureData(copyLayout);
|
std::vector<RGBA8> textureArrayData = GetExpectedTextureData(copyLayout);
|
||||||
|
{
|
||||||
// TODO(jiawei.shao@intel.com): copy into multiple texture array layers in one
|
wgpu::Buffer uploadBuffer =
|
||||||
// buffer-to-texture copy command.
|
utils::CreateBufferFromData(device, textureArrayData.data(),
|
||||||
wgpu::Buffer uploadBuffer = utils::CreateBufferFromData(
|
copyLayout.byteLength, wgpu::BufferUsage::CopySrc);
|
||||||
device, textureArrayData.data(), copyLayout.byteLength, wgpu::BufferUsage::CopySrc);
|
|
||||||
uint64_t uploadBufferOffset = 0;
|
|
||||||
for (uint32_t slice = 0; slice < textureSpec.textureSize.depth; ++slice) {
|
|
||||||
wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
|
wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
|
||||||
uploadBuffer, uploadBufferOffset, copyLayout.bytesPerRow, 0);
|
uploadBuffer, 0, copyLayout.bytesPerRow, bufferSpec.rowsPerImage);
|
||||||
wgpu::TextureCopyView textureCopyView =
|
wgpu::TextureCopyView textureCopyView =
|
||||||
utils::CreateTextureCopyView(texture, textureSpec.level, {0, 0, slice});
|
utils::CreateTextureCopyView(texture, textureSpec.level, {0, 0, 0});
|
||||||
wgpu::Extent3D copyOneLayerSize = {copyLayout.mipSize.width,
|
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Layout.mipSize);
|
||||||
copyLayout.mipSize.height, 1};
|
|
||||||
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©OneLayerSize);
|
|
||||||
uploadBufferOffset += copyLayout.bytesPerImage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a buffer of `size` and populate it with empty data (0,0,0,0) Note:
|
// Create a buffer of `size` and populate it with empty data (0,0,0,0) Note:
|
||||||
|
@ -128,31 +125,21 @@ class CopyTests_T2B : public CopyTests {
|
||||||
utils::CreateBufferFromData(device, emptyData.data(), bufferSpec.size,
|
utils::CreateBufferFromData(device, emptyData.data(), bufferSpec.size,
|
||||||
wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
|
wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
|
||||||
|
|
||||||
const uint32_t maxArrayLayer = textureSpec.copyOrigin.z + copySize.depth;
|
{
|
||||||
|
wgpu::TextureCopyView textureCopyView =
|
||||||
// TODO(jiawei.shao@intel.com): copy from multiple texture array layers in one
|
utils::CreateTextureCopyView(texture, textureSpec.level, textureSpec.copyOrigin);
|
||||||
// texture-to-buffer copy command.
|
wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
|
||||||
uint64_t bufferOffset = bufferSpec.offset;
|
buffer, bufferSpec.offset, bufferSpec.bytesPerRow, bufferSpec.rowsPerImage);
|
||||||
for (uint32_t slice = textureSpec.copyOrigin.z; slice < maxArrayLayer; ++slice) {
|
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Size);
|
||||||
// Copy the region [(`x`, `y`, slice), (`x + testCopySize.width, `y +
|
|
||||||
// testCopySize.height`, 1)] from the `level` mip into the buffer at `offset +
|
|
||||||
// bufferSpec.size * slice` and `bytesPerRow`
|
|
||||||
wgpu::TextureCopyView textureCopyView = utils::CreateTextureCopyView(
|
|
||||||
texture, textureSpec.level,
|
|
||||||
{textureSpec.copyOrigin.x, textureSpec.copyOrigin.y, slice});
|
|
||||||
wgpu::BufferCopyView bufferCopyView =
|
|
||||||
utils::CreateBufferCopyView(buffer, bufferOffset, bufferSpec.bytesPerRow, 0);
|
|
||||||
wgpu::Extent3D copyOneLayerSize = {copySize.width, copySize.height, 1};
|
|
||||||
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©OneLayerSize);
|
|
||||||
bufferOffset += copyLayout.bytesPerImage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::CommandBuffer commands = encoder.Finish();
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
queue.Submit(1, &commands);
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
bufferOffset = bufferSpec.offset;
|
uint64_t bufferOffset = bufferSpec.offset;
|
||||||
const uint32_t texelCountInCopyRegion =
|
const uint32_t texelCountInCopyRegion =
|
||||||
bufferSpec.bytesPerRow / bytesPerTexel * (copySize.height - 1) + copySize.width;
|
bufferSpec.bytesPerRow / bytesPerTexel * (copySize.height - 1) + copySize.width;
|
||||||
|
const uint32_t maxArrayLayer = textureSpec.copyOrigin.z + copySize.depth;
|
||||||
std::vector<RGBA8> expected(texelCountInCopyRegion);
|
std::vector<RGBA8> expected(texelCountInCopyRegion);
|
||||||
for (uint32_t slice = textureSpec.copyOrigin.z; slice < maxArrayLayer; ++slice) {
|
for (uint32_t slice = textureSpec.copyOrigin.z; slice < maxArrayLayer; ++slice) {
|
||||||
// Pack the data used to create the upload buffer in the specified copy region to have
|
// Pack the data used to create the upload buffer in the specified copy region to have
|
||||||
|
@ -218,34 +205,23 @@ protected:
|
||||||
|
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
|
||||||
const uint32_t rowsPerImage = textureSpec.textureSize.height >> textureSpec.level;
|
|
||||||
const utils::BufferTextureCopyLayout copyLayout =
|
const utils::BufferTextureCopyLayout copyLayout =
|
||||||
utils::GetBufferTextureCopyLayoutForTexture2DAtLevel(
|
utils::GetBufferTextureCopyLayoutForTexture2DAtLevel(
|
||||||
kTextureFormat, textureSpec.textureSize, textureSpec.level, rowsPerImage);
|
kTextureFormat, textureSpec.textureSize, textureSpec.level,
|
||||||
|
bufferSpec.rowsPerImage);
|
||||||
|
|
||||||
const uint32_t maxArrayLayer = textureSpec.copyOrigin.z + copySize.depth;
|
const uint32_t maxArrayLayer = textureSpec.copyOrigin.z + copySize.depth;
|
||||||
|
|
||||||
// TODO(jiawei.shao@intel.com): support copying into multiple texture array layers in one
|
wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
|
||||||
// copy command.
|
buffer, bufferSpec.offset, bufferSpec.bytesPerRow, bufferSpec.rowsPerImage);
|
||||||
uint64_t bufferOffset = bufferSpec.offset;
|
wgpu::TextureCopyView textureCopyView =
|
||||||
for (uint32_t slice = textureSpec.copyOrigin.z; slice < maxArrayLayer; ++slice) {
|
utils::CreateTextureCopyView(texture, textureSpec.level, textureSpec.copyOrigin);
|
||||||
// Copy to the region [(`x`, `y`, `slice`), (`x + testCopySize.width, `y +
|
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Size);
|
||||||
// testCopySize.height`, 1] at the `level` mip
|
|
||||||
// from the buffer at the specified `offset` and `bytesPerRow`
|
|
||||||
wgpu::BufferCopyView bufferCopyView =
|
|
||||||
utils::CreateBufferCopyView(buffer, bufferOffset, bufferSpec.bytesPerRow, 0);
|
|
||||||
wgpu::TextureCopyView textureCopyView = utils::CreateTextureCopyView(
|
|
||||||
texture, textureSpec.level,
|
|
||||||
{textureSpec.copyOrigin.x, textureSpec.copyOrigin.y, slice});
|
|
||||||
wgpu::Extent3D copyOneLayerSize = {copySize.width, copySize.height, 1};
|
|
||||||
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©OneLayerSize);
|
|
||||||
bufferOffset += copyLayout.bytesPerImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
wgpu::CommandBuffer commands = encoder.Finish();
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
queue.Submit(1, &commands);
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
bufferOffset = bufferSpec.offset;
|
uint64_t bufferOffset = bufferSpec.offset;
|
||||||
const uint32_t texelCountLastLayer =
|
const uint32_t texelCountLastLayer =
|
||||||
copyLayout.texelBlocksPerRow * (copyLayout.mipSize.height - 1) +
|
copyLayout.texelBlocksPerRow * (copyLayout.mipSize.height - 1) +
|
||||||
copyLayout.mipSize.width;
|
copyLayout.mipSize.width;
|
||||||
|
@ -305,30 +281,21 @@ class CopyTests_T2T : public CopyTests {
|
||||||
|
|
||||||
// Create an upload buffer and use it to populate the current slice of the texture in
|
// Create an upload buffer and use it to populate the current slice of the texture in
|
||||||
// `level` mip level
|
// `level` mip level
|
||||||
const uint32_t rowsPerImage = srcSpec.textureSize.height >> srcSpec.level;
|
|
||||||
const utils::BufferTextureCopyLayout copyLayout =
|
const utils::BufferTextureCopyLayout copyLayout =
|
||||||
utils::GetBufferTextureCopyLayoutForTexture2DAtLevel(
|
utils::GetBufferTextureCopyLayoutForTexture2DAtLevel(
|
||||||
kTextureFormat,
|
kTextureFormat,
|
||||||
{srcSpec.textureSize.width, srcSpec.textureSize.height, copySize.depth},
|
{srcSpec.textureSize.width, srcSpec.textureSize.height, copySize.depth},
|
||||||
srcSpec.level, rowsPerImage);
|
srcSpec.level, 0);
|
||||||
|
|
||||||
const std::vector<RGBA8> textureArrayCopyData = GetExpectedTextureData(copyLayout);
|
const std::vector<RGBA8> textureArrayCopyData = GetExpectedTextureData(copyLayout);
|
||||||
|
|
||||||
// TODO(jiawei.shao@intel.com): support copying into multiple contiguous array layers in one
|
|
||||||
// copyBufferToTexture() call.
|
|
||||||
wgpu::Buffer uploadBuffer = utils::CreateBufferFromData(
|
wgpu::Buffer uploadBuffer = utils::CreateBufferFromData(
|
||||||
device, textureArrayCopyData.data(), copyLayout.byteLength, wgpu::BufferUsage::CopySrc);
|
device, textureArrayCopyData.data(), copyLayout.byteLength, wgpu::BufferUsage::CopySrc);
|
||||||
uint64_t uploadBufferOffset = 0;
|
wgpu::BufferCopyView bufferCopyView =
|
||||||
for (uint32_t slice = 0; slice < copySize.depth; ++slice) {
|
utils::CreateBufferCopyView(uploadBuffer, 0, copyLayout.bytesPerRow, 0);
|
||||||
wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
|
wgpu::TextureCopyView textureCopyView =
|
||||||
uploadBuffer, uploadBufferOffset, copyLayout.bytesPerRow, 0);
|
utils::CreateTextureCopyView(srcTexture, srcSpec.level, {0, 0, srcSpec.copyOrigin.z});
|
||||||
wgpu::TextureCopyView textureCopyView = utils::CreateTextureCopyView(
|
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Layout.mipSize);
|
||||||
srcTexture, srcSpec.level, {0, 0, srcSpec.copyOrigin.z + slice});
|
|
||||||
wgpu::Extent3D copyOneLayerSize = {copyLayout.mipSize.width, copyLayout.mipSize.height,
|
|
||||||
1};
|
|
||||||
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©OneLayerSize);
|
|
||||||
uploadBufferOffset += copyLayout.bytesPerImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the texture to texture copy
|
// Perform the texture to texture copy
|
||||||
wgpu::TextureCopyView srcTextureCopyView =
|
wgpu::TextureCopyView srcTextureCopyView =
|
||||||
|
@ -700,8 +667,12 @@ TEST_P(CopyTests_T2B, RowPitchUnaligned) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that copying regions of each texture 2D array layer works
|
// Test that copying whole texture 2D array layers in one texture-to-buffer-copy works.
|
||||||
TEST_P(CopyTests_T2B, Texture2DArrayRegion) {
|
TEST_P(CopyTests_T2B, Texture2DArrayRegion) {
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layer fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
constexpr uint32_t kWidth = 256;
|
constexpr uint32_t kWidth = 256;
|
||||||
constexpr uint32_t kHeight = 128;
|
constexpr uint32_t kHeight = 128;
|
||||||
constexpr uint32_t kLayers = 6u;
|
constexpr uint32_t kLayers = 6u;
|
||||||
|
@ -714,8 +685,12 @@ TEST_P(CopyTests_T2B, Texture2DArrayRegion) {
|
||||||
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight, kLayers), {kWidth, kHeight, kLayers});
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight, kLayers), {kWidth, kHeight, kLayers});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that copying a sub-region of each texture 2D array layer works
|
// Test that copying a range of texture 2D array layers in one texture-to-buffer-copy works.
|
||||||
TEST_P(CopyTests_T2B, Texture2DArraySubRegion) {
|
TEST_P(CopyTests_T2B, Texture2DArraySubRegion) {
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layer fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
constexpr uint32_t kWidth = 256;
|
constexpr uint32_t kWidth = 256;
|
||||||
constexpr uint32_t kHeight = 128;
|
constexpr uint32_t kHeight = 128;
|
||||||
constexpr uint32_t kLayers = 6u;
|
constexpr uint32_t kLayers = 6u;
|
||||||
|
@ -733,6 +708,10 @@ TEST_P(CopyTests_T2B, Texture2DArraySubRegion) {
|
||||||
|
|
||||||
// Test that copying texture 2D array mips with 256-byte aligned sizes works
|
// Test that copying texture 2D array mips with 256-byte aligned sizes works
|
||||||
TEST_P(CopyTests_T2B, Texture2DArrayMip) {
|
TEST_P(CopyTests_T2B, Texture2DArrayMip) {
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
constexpr uint32_t kWidth = 256;
|
constexpr uint32_t kWidth = 256;
|
||||||
constexpr uint32_t kHeight = 128;
|
constexpr uint32_t kHeight = 128;
|
||||||
constexpr uint32_t kLayers = 6u;
|
constexpr uint32_t kLayers = 6u;
|
||||||
|
@ -750,6 +729,31 @@ TEST_P(CopyTests_T2B, Texture2DArrayMip) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that copying from a range of texture 2D array layers in one texture-to-buffer-copy when
|
||||||
|
// RowsPerImage is not equal to the height of the texture works.
|
||||||
|
TEST_P(CopyTests_T2B, Texture2DArrayRegionNonzeroRowsPerImage) {
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
|
constexpr uint32_t kWidth = 256;
|
||||||
|
constexpr uint32_t kHeight = 128;
|
||||||
|
constexpr uint32_t kLayers = 6u;
|
||||||
|
constexpr uint32_t kBaseLayer = 2u;
|
||||||
|
constexpr uint32_t kCopyLayers = 3u;
|
||||||
|
|
||||||
|
constexpr uint32_t kRowsPerImage = kHeight * 2;
|
||||||
|
|
||||||
|
TextureSpec textureSpec;
|
||||||
|
textureSpec.copyOrigin = {0, 0, kBaseLayer};
|
||||||
|
textureSpec.textureSize = {kWidth, kHeight, kLayers};
|
||||||
|
textureSpec.level = 0;
|
||||||
|
|
||||||
|
BufferSpec bufferSpec = MinimumBufferSpec(kWidth, kRowsPerImage, kCopyLayers, false);
|
||||||
|
bufferSpec.rowsPerImage = kRowsPerImage;
|
||||||
|
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kCopyLayers});
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(CopyTests_T2B, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
|
DAWN_INSTANTIATE_TEST(CopyTests_T2B, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
|
||||||
|
|
||||||
// Test that copying an entire texture with 256-byte aligned dimensions works
|
// Test that copying an entire texture with 256-byte aligned dimensions works
|
||||||
|
@ -1038,8 +1042,12 @@ TEST_P(CopyTests_B2T, RowPitchUnaligned) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that copying into regions of each texture 2D array layer works
|
// Test that copying whole texture 2D array layers in one texture-to-buffer-copy works.
|
||||||
TEST_P(CopyTests_B2T, Texture2DArrayRegion) {
|
TEST_P(CopyTests_B2T, Texture2DArrayRegion) {
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
constexpr uint32_t kWidth = 256;
|
constexpr uint32_t kWidth = 256;
|
||||||
constexpr uint32_t kHeight = 128;
|
constexpr uint32_t kHeight = 128;
|
||||||
constexpr uint32_t kLayers = 6u;
|
constexpr uint32_t kLayers = 6u;
|
||||||
|
@ -1052,8 +1060,12 @@ TEST_P(CopyTests_B2T, Texture2DArrayRegion) {
|
||||||
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight, kLayers), {kWidth, kHeight, kLayers});
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight, kLayers), {kWidth, kHeight, kLayers});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that copying into a sub-region of each texture 2D array layer works
|
// Test that copying a range of texture 2D array layers in one texture-to-buffer-copy works.
|
||||||
TEST_P(CopyTests_B2T, Texture2DArraySubRegion) {
|
TEST_P(CopyTests_B2T, Texture2DArraySubRegion) {
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
constexpr uint32_t kWidth = 256;
|
constexpr uint32_t kWidth = 256;
|
||||||
constexpr uint32_t kHeight = 128;
|
constexpr uint32_t kHeight = 128;
|
||||||
constexpr uint32_t kLayers = 6u;
|
constexpr uint32_t kLayers = 6u;
|
||||||
|
@ -1069,6 +1081,31 @@ TEST_P(CopyTests_B2T, Texture2DArraySubRegion) {
|
||||||
{kWidth, kHeight, kCopyLayers});
|
{kWidth, kHeight, kCopyLayers});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that copying into a range of texture 2D array layers in one texture-to-buffer-copy when
|
||||||
|
// RowsPerImage is not equal to the height of the texture works.
|
||||||
|
TEST_P(CopyTests_B2T, Texture2DArrayRegionNonzeroRowsPerImage) {
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
|
constexpr uint32_t kWidth = 256;
|
||||||
|
constexpr uint32_t kHeight = 128;
|
||||||
|
constexpr uint32_t kLayers = 6u;
|
||||||
|
constexpr uint32_t kBaseLayer = 2u;
|
||||||
|
constexpr uint32_t kCopyLayers = 3u;
|
||||||
|
|
||||||
|
constexpr uint32_t kRowsPerImage = kHeight * 2;
|
||||||
|
|
||||||
|
TextureSpec textureSpec;
|
||||||
|
textureSpec.copyOrigin = {0, 0, kBaseLayer};
|
||||||
|
textureSpec.textureSize = {kWidth, kHeight, kLayers};
|
||||||
|
textureSpec.level = 0;
|
||||||
|
|
||||||
|
BufferSpec bufferSpec = MinimumBufferSpec(kWidth, kRowsPerImage, kCopyLayers, false);
|
||||||
|
bufferSpec.rowsPerImage = kRowsPerImage;
|
||||||
|
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kCopyLayers});
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(CopyTests_B2T, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
|
DAWN_INSTANTIATE_TEST(CopyTests_B2T, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
|
||||||
|
|
||||||
TEST_P(CopyTests_T2T, Texture) {
|
TEST_P(CopyTests_T2T, Texture) {
|
||||||
|
|
|
@ -460,23 +460,14 @@ class StorageTextureTests : public DawnTest {
|
||||||
CreateTexture(format, wgpu::TextureUsage::Storage | wgpu::TextureUsage::CopyDst, kWidth,
|
CreateTexture(format, wgpu::TextureUsage::Storage | wgpu::TextureUsage::CopyDst, kWidth,
|
||||||
kHeight, arrayLayerCount);
|
kHeight, arrayLayerCount);
|
||||||
|
|
||||||
const wgpu::Extent3D copyExtent = {kWidth, kHeight, 1};
|
|
||||||
|
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
|
||||||
// TODO(jiawei.shao@intel.com): copy multiple array layers in one CopyBufferToTexture() when
|
const wgpu::Extent3D copyExtent = {kWidth, kHeight, arrayLayerCount};
|
||||||
// it is supported.
|
wgpu::BufferCopyView bufferCopyView =
|
||||||
for (uint32_t layer = 0; layer < arrayLayerCount; ++layer) {
|
utils::CreateBufferCopyView(uploadBuffer, 0, kTextureBytesPerRowAlignment, 0);
|
||||||
wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
|
wgpu::TextureCopyView textureCopyView;
|
||||||
uploadBuffer, kTextureBytesPerRowAlignment * kHeight * layer,
|
textureCopyView.texture = outputTexture;
|
||||||
kTextureBytesPerRowAlignment, 0);
|
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Extent);
|
||||||
|
|
||||||
wgpu::TextureCopyView textureCopyView;
|
|
||||||
textureCopyView.texture = outputTexture;
|
|
||||||
textureCopyView.origin.z = layer;
|
|
||||||
|
|
||||||
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Extent);
|
|
||||||
}
|
|
||||||
|
|
||||||
wgpu::CommandBuffer commandBuffer = encoder.Finish();
|
wgpu::CommandBuffer commandBuffer = encoder.Finish();
|
||||||
queue.Submit(1, &commandBuffer);
|
queue.Submit(1, &commandBuffer);
|
||||||
|
@ -643,23 +634,14 @@ class StorageTextureTests : public DawnTest {
|
||||||
static_cast<uint32_t>(expectedData.size() / texelSize / (kWidth * kHeight));
|
static_cast<uint32_t>(expectedData.size() / texelSize / (kWidth * kHeight));
|
||||||
wgpu::Buffer resultBuffer = CreateEmptyBufferForTextureCopy(texelSize, arrayLayerCount);
|
wgpu::Buffer resultBuffer = CreateEmptyBufferForTextureCopy(texelSize, arrayLayerCount);
|
||||||
|
|
||||||
const wgpu::Extent3D copyExtent = {kWidth, kHeight, 1};
|
|
||||||
|
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
|
||||||
// TODO(jiawei.shao@intel.com): copy multiple array layers in one CopyTextureToBuffer() when
|
const wgpu::Extent3D copyExtent = {kWidth, kHeight, arrayLayerCount};
|
||||||
// it is supported.
|
wgpu::TextureCopyView textureCopyView =
|
||||||
for (uint32_t layer = 0; layer < arrayLayerCount; ++layer) {
|
utils::CreateTextureCopyView(writeonlyStorageTexture, 0, {0, 0, 0});
|
||||||
wgpu::TextureCopyView textureCopyView;
|
wgpu::BufferCopyView bufferCopyView =
|
||||||
textureCopyView.texture = writeonlyStorageTexture;
|
utils::CreateBufferCopyView(resultBuffer, 0, kTextureBytesPerRowAlignment, 0);
|
||||||
textureCopyView.origin.z = layer;
|
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Extent);
|
||||||
|
|
||||||
const uint64_t bufferOffset = kTextureBytesPerRowAlignment * kHeight * layer;
|
|
||||||
wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
|
|
||||||
resultBuffer, bufferOffset, kTextureBytesPerRowAlignment, 0);
|
|
||||||
|
|
||||||
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Extent);
|
|
||||||
}
|
|
||||||
wgpu::CommandBuffer commandBuffer = encoder.Finish();
|
wgpu::CommandBuffer commandBuffer = encoder.Finish();
|
||||||
queue.Submit(1, &commandBuffer);
|
queue.Submit(1, &commandBuffer);
|
||||||
|
|
||||||
|
@ -955,6 +937,10 @@ TEST_P(StorageTextureTests, Readonly2DArrayStorageTexture) {
|
||||||
// bug in spvc parser is fixed.
|
// bug in spvc parser is fixed.
|
||||||
DAWN_SKIP_TEST_IF(IsSpvcParserBeingUsed());
|
DAWN_SKIP_TEST_IF(IsSpvcParserBeingUsed());
|
||||||
|
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layer fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
constexpr uint32_t kArrayLayerCount = 3u;
|
constexpr uint32_t kArrayLayerCount = 3u;
|
||||||
|
|
||||||
constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::R32Uint;
|
constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::R32Uint;
|
||||||
|
@ -993,6 +979,10 @@ TEST_P(StorageTextureTests, Writeonly2DArrayStorageTexture) {
|
||||||
// bug in spvc parser is fixed.
|
// bug in spvc parser is fixed.
|
||||||
DAWN_SKIP_TEST_IF(IsD3D12() && IsSpvcParserBeingUsed());
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsSpvcParserBeingUsed());
|
||||||
|
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layer fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
constexpr uint32_t kArrayLayerCount = 3u;
|
constexpr uint32_t kArrayLayerCount = 3u;
|
||||||
|
|
||||||
constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::R32Uint;
|
constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::R32Uint;
|
||||||
|
|
|
@ -130,6 +130,49 @@ TEST_P(TextureZeroInitTest, CopyTextureToBufferSource) {
|
||||||
EXPECT_EQ(true, dawn_native::IsTextureSubresourceInitialized(texture.Get(), 0, 1, 0, 1));
|
EXPECT_EQ(true, dawn_native::IsTextureSubresourceInitialized(texture.Get(), 0, 1, 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This tests that the code path of CopyTextureToBuffer with multiple texture array layers clears
|
||||||
|
// correctly to Zero after first usage
|
||||||
|
TEST_P(TextureZeroInitTest, CopyMultipleTextureArrayLayersToBufferSource) {
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
|
constexpr uint32_t kArrayLayers = 6u;
|
||||||
|
|
||||||
|
const wgpu::TextureDescriptor descriptor = CreateTextureDescriptor(
|
||||||
|
1, kArrayLayers, wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::CopySrc,
|
||||||
|
kColorFormat);
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||||
|
|
||||||
|
const uint32_t bytesPerRow = utils::GetMinimumBytesPerRow(kColorFormat, kSize);
|
||||||
|
wgpu::BufferDescriptor bufferDescriptor;
|
||||||
|
bufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
||||||
|
bufferDescriptor.size =
|
||||||
|
utils::GetBytesInBufferTextureCopy(kColorFormat, kSize, bytesPerRow, kSize, kArrayLayers);
|
||||||
|
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
|
||||||
|
|
||||||
|
const wgpu::BufferCopyView bufferCopyView =
|
||||||
|
utils::CreateBufferCopyView(buffer, 0, bytesPerRow, 0);
|
||||||
|
const wgpu::TextureCopyView textureCopyView =
|
||||||
|
utils::CreateTextureCopyView(texture, 0, {0, 0, 0});
|
||||||
|
const wgpu::Extent3D copySize = {kSize, kSize, kArrayLayers};
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Size);
|
||||||
|
wgpu::CommandBuffer commandBuffer = encoder.Finish();
|
||||||
|
|
||||||
|
// Expect texture to be lazy initialized.
|
||||||
|
EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commandBuffer));
|
||||||
|
|
||||||
|
// Expect texture subresource initialized to be true
|
||||||
|
EXPECT_TRUE(dawn_native::IsTextureSubresourceInitialized(texture.Get(), 0, 1, 0, kArrayLayers));
|
||||||
|
|
||||||
|
const std::vector<RGBA8> kExpectedAllZero(kSize * kSize, {0, 0, 0, 0});
|
||||||
|
for (uint32_t layer = 0; layer < kArrayLayers; ++layer) {
|
||||||
|
EXPECT_TEXTURE_RGBA8_EQ(kExpectedAllZero.data(), texture, 0, 0, kSize, kSize, 0, layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test that non-zero mip level clears subresource to Zero after first use
|
// Test that non-zero mip level clears subresource to Zero after first use
|
||||||
// This goes through the BeginRenderPass's code path
|
// This goes through the BeginRenderPass's code path
|
||||||
TEST_P(TextureZeroInitTest, RenderingMipMapClearsToZero) {
|
TEST_P(TextureZeroInitTest, RenderingMipMapClearsToZero) {
|
||||||
|
@ -282,6 +325,47 @@ TEST_P(TextureZeroInitTest, CopyBufferToTextureHalf) {
|
||||||
EXPECT_EQ(true, dawn_native::IsTextureSubresourceInitialized(texture.Get(), 0, 1, 0, 1));
|
EXPECT_EQ(true, dawn_native::IsTextureSubresourceInitialized(texture.Get(), 0, 1, 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This tests CopyBufferToTexture fully overwrites a range of subresources, so lazy initialization
|
||||||
|
// is needed for neither the subresources involved in the copy nor the other subresources.
|
||||||
|
TEST_P(TextureZeroInitTest, CopyBufferToTextureMultipleArrayLayers) {
|
||||||
|
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
|
||||||
|
// with swiftshader.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
|
||||||
|
wgpu::TextureDescriptor descriptor = CreateTextureDescriptor(
|
||||||
|
1, 6, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc, kColorFormat);
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||||
|
|
||||||
|
constexpr uint32_t kBaseArrayLayer = 2u;
|
||||||
|
constexpr uint32_t kCopyLayerCount = 3u;
|
||||||
|
std::vector<uint8_t> data(kFormatBlockByteSize * kSize * kSize * kCopyLayerCount, 100);
|
||||||
|
wgpu::Buffer stagingBuffer = utils::CreateBufferFromData(
|
||||||
|
device, data.data(), static_cast<uint32_t>(data.size()), wgpu::BufferUsage::CopySrc);
|
||||||
|
|
||||||
|
const wgpu::BufferCopyView bufferCopyView =
|
||||||
|
utils::CreateBufferCopyView(stagingBuffer, 0, kSize * kFormatBlockByteSize, 0);
|
||||||
|
const wgpu::TextureCopyView textureCopyView =
|
||||||
|
utils::CreateTextureCopyView(texture, 0, {0, 0, kBaseArrayLayer});
|
||||||
|
const wgpu::Extent3D copySize = {kSize, kSize, kCopyLayerCount};
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Size);
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
|
||||||
|
// The copy overwrites the whole subresources su we don't need to do lazy initialization on
|
||||||
|
// them.
|
||||||
|
EXPECT_LAZY_CLEAR(0u, queue.Submit(1, &commands));
|
||||||
|
|
||||||
|
// Expect texture subresource initialized to be true
|
||||||
|
EXPECT_TRUE(dawn_native::IsTextureSubresourceInitialized(texture.Get(), 0, 1, kBaseArrayLayer,
|
||||||
|
kCopyLayerCount));
|
||||||
|
|
||||||
|
const std::vector<RGBA8> expected100(kSize * kSize, {100, 100, 100, 100});
|
||||||
|
for (uint32_t layer = kBaseArrayLayer; layer < kBaseArrayLayer + kCopyLayerCount; ++layer) {
|
||||||
|
EXPECT_TEXTURE_RGBA8_EQ(expected100.data(), texture, 0, 0, kSize, kSize, 0, layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This tests CopyTextureToTexture fully overwrites copy so lazy init is not needed.
|
// This tests CopyTextureToTexture fully overwrites copy so lazy init is not needed.
|
||||||
TEST_P(TextureZeroInitTest, CopyTextureToTexture) {
|
TEST_P(TextureZeroInitTest, CopyTextureToTexture) {
|
||||||
wgpu::TextureDescriptor srcDescriptor = CreateTextureDescriptor(
|
wgpu::TextureDescriptor srcDescriptor = CreateTextureDescriptor(
|
||||||
|
|
|
@ -384,6 +384,7 @@ namespace utils {
|
||||||
uint32_t bytesPerRow,
|
uint32_t bytesPerRow,
|
||||||
uint32_t rowsPerImage,
|
uint32_t rowsPerImage,
|
||||||
uint32_t copyArrayLayerCount) {
|
uint32_t copyArrayLayerCount) {
|
||||||
|
ASSERT(rowsPerImage > 0);
|
||||||
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
||||||
const uint32_t bytesAtLastImage = bytesPerRow * (rowsPerImage - 1) + bytesPerTexel * width;
|
const uint32_t bytesAtLastImage = bytesPerRow * (rowsPerImage - 1) + bytesPerTexel * width;
|
||||||
return bytesPerRow * rowsPerImage * (copyArrayLayerCount - 1) + bytesAtLastImage;
|
return bytesPerRow * rowsPerImage * (copyArrayLayerCount - 1) + bytesAtLastImage;
|
||||||
|
@ -401,11 +402,13 @@ namespace utils {
|
||||||
textureSizeAtLevel0.height >> mipmapLevel, textureSizeAtLevel0.depth};
|
textureSizeAtLevel0.height >> mipmapLevel, textureSizeAtLevel0.depth};
|
||||||
|
|
||||||
layout.bytesPerRow = GetMinimumBytesPerRow(format, layout.mipSize.width);
|
layout.bytesPerRow = GetMinimumBytesPerRow(format, layout.mipSize.width);
|
||||||
layout.bytesPerImage = layout.bytesPerRow * rowsPerImage;
|
|
||||||
|
uint32_t appliedRowsPerImage = rowsPerImage > 0 ? rowsPerImage : layout.mipSize.height;
|
||||||
|
layout.bytesPerImage = layout.bytesPerRow * appliedRowsPerImage;
|
||||||
|
|
||||||
layout.byteLength =
|
layout.byteLength =
|
||||||
GetBytesInBufferTextureCopy(format, layout.mipSize.width, layout.bytesPerRow,
|
GetBytesInBufferTextureCopy(format, layout.mipSize.width, layout.bytesPerRow,
|
||||||
layout.mipSize.height, textureSizeAtLevel0.depth);
|
appliedRowsPerImage, textureSizeAtLevel0.depth);
|
||||||
|
|
||||||
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
||||||
layout.texelBlocksPerRow = layout.bytesPerRow / bytesPerTexel;
|
layout.texelBlocksPerRow = layout.bytesPerRow / bytesPerTexel;
|
||||||
|
|
Loading…
Reference in New Issue