Implement copy for 3D texture on D3D12: non-zero mip
The change implements copy non-zero mip level for 3D textures on D3D12 when the texture has multiple mip levels. The texture size on level 0 can be either 256-byte aligned or 256-byte unaligned(its size is non-power-of-two). Bug: dawn:547 Change-Id: I8ed74fa587cfd814e7f526173dcb653d0a252a1e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/51201 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Yunchao He <yunchao.he@intel.com>
This commit is contained in:
parent
aec5b98670
commit
e5b9903cc1
|
@ -151,8 +151,8 @@ class CopyTests_T2B : public CopyTests {
|
||||||
// Layout for initial data upload to texture.
|
// Layout for initial data upload to texture.
|
||||||
// Some parts of this result are also reused later.
|
// Some parts of this result are also reused later.
|
||||||
const utils::TextureDataCopyLayout copyLayout =
|
const utils::TextureDataCopyLayout copyLayout =
|
||||||
utils::GetTextureDataCopyLayoutForTexture2DAtLevel(
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
||||||
textureSpec.format, textureSpec.textureSize, textureSpec.copyLevel);
|
textureSpec.format, textureSpec.textureSize, textureSpec.copyLevel, dimension);
|
||||||
|
|
||||||
// Initialize the source texture
|
// Initialize the source texture
|
||||||
std::vector<RGBA8> textureArrayData = GetExpectedTextureDataRGBA8(copyLayout);
|
std::vector<RGBA8> textureArrayData = GetExpectedTextureDataRGBA8(copyLayout);
|
||||||
|
@ -279,8 +279,8 @@ class CopyTests_B2T : public CopyTests {
|
||||||
queue.Submit(1, &commands);
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
const utils::TextureDataCopyLayout copyLayout =
|
const utils::TextureDataCopyLayout copyLayout =
|
||||||
utils::GetTextureDataCopyLayoutForTexture2DAtLevel(
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
||||||
textureSpec.format, textureSpec.textureSize, textureSpec.copyLevel,
|
textureSpec.format, textureSpec.textureSize, textureSpec.copyLevel, dimension,
|
||||||
bufferSpec.rowsPerImage);
|
bufferSpec.rowsPerImage);
|
||||||
|
|
||||||
uint32_t copyLayer = copySize.depthOrArrayLayers;
|
uint32_t copyLayer = copySize.depthOrArrayLayers;
|
||||||
|
@ -367,11 +367,11 @@ 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 utils::TextureDataCopyLayout srcDataCopyLayout =
|
const utils::TextureDataCopyLayout srcDataCopyLayout =
|
||||||
utils::GetTextureDataCopyLayoutForTexture2DAtLevel(
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
||||||
format,
|
format,
|
||||||
{srcSpec.textureSize.width, srcSpec.textureSize.height,
|
{srcSpec.textureSize.width, srcSpec.textureSize.height,
|
||||||
copySize.depthOrArrayLayers},
|
copySize.depthOrArrayLayers},
|
||||||
srcSpec.copyLevel);
|
srcSpec.copyLevel, srcDimension);
|
||||||
|
|
||||||
// Initialize the source texture
|
// Initialize the source texture
|
||||||
const std::vector<uint8_t> srcTextureCopyData = GetExpectedTextureData(srcDataCopyLayout);
|
const std::vector<uint8_t> srcTextureCopyData = GetExpectedTextureData(srcDataCopyLayout);
|
||||||
|
@ -397,11 +397,11 @@ class CopyTests_T2T : public CopyTests {
|
||||||
// Copy the data from the srcSpec.copyOrigin.z-th layer to (srcSpec.copyOrigin.z +
|
// Copy the data from the srcSpec.copyOrigin.z-th layer to (srcSpec.copyOrigin.z +
|
||||||
// copySize.depthOrArrayLayers)-th layer of dstTexture to outputBuffer
|
// copySize.depthOrArrayLayers)-th layer of dstTexture to outputBuffer
|
||||||
const utils::TextureDataCopyLayout dstDataCopyLayout =
|
const utils::TextureDataCopyLayout dstDataCopyLayout =
|
||||||
utils::GetTextureDataCopyLayoutForTexture2DAtLevel(
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
||||||
format,
|
format,
|
||||||
{dstSpec.textureSize.width, dstSpec.textureSize.height,
|
{dstSpec.textureSize.width, dstSpec.textureSize.height,
|
||||||
copySize.depthOrArrayLayers},
|
copySize.depthOrArrayLayers},
|
||||||
dstSpec.copyLevel);
|
dstSpec.copyLevel, dstDimension);
|
||||||
wgpu::BufferDescriptor outputBufferDescriptor;
|
wgpu::BufferDescriptor outputBufferDescriptor;
|
||||||
outputBufferDescriptor.size = dstDataCopyLayout.byteLength;
|
outputBufferDescriptor.size = dstDataCopyLayout.byteLength;
|
||||||
outputBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
outputBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
||||||
|
@ -1161,6 +1161,44 @@ TEST_P(CopyTests_T2B, Texture3DCopyHeightIsOneCopyWidthIsSmall) {
|
||||||
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kDepth}, wgpu::TextureDimension::e3D);
|
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kDepth}, wgpu::TextureDimension::e3D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that copying texture 3D array mips with 256-byte aligned sizes works
|
||||||
|
TEST_P(CopyTests_T2B, Texture3DMipAligned) {
|
||||||
|
constexpr uint32_t kWidth = 256;
|
||||||
|
constexpr uint32_t kHeight = 128;
|
||||||
|
constexpr uint32_t kDepth = 64u;
|
||||||
|
|
||||||
|
TextureSpec defaultTextureSpec;
|
||||||
|
defaultTextureSpec.textureSize = {kWidth, kHeight, kDepth};
|
||||||
|
|
||||||
|
for (unsigned int i = 1; i < 6; ++i) {
|
||||||
|
TextureSpec textureSpec = defaultTextureSpec;
|
||||||
|
textureSpec.copyLevel = i;
|
||||||
|
textureSpec.levelCount = i + 1;
|
||||||
|
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth >> i, kHeight >> i, kDepth >> i),
|
||||||
|
{kWidth >> i, kHeight >> i, kDepth >> i}, wgpu::TextureDimension::e3D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that copying texture 3D array mips with 256-byte unaligned sizes works
|
||||||
|
TEST_P(CopyTests_T2B, Texture3DMipUnaligned) {
|
||||||
|
constexpr uint32_t kWidth = 261;
|
||||||
|
constexpr uint32_t kHeight = 123;
|
||||||
|
constexpr uint32_t kDepth = 69u;
|
||||||
|
|
||||||
|
TextureSpec defaultTextureSpec;
|
||||||
|
defaultTextureSpec.textureSize = {kWidth, kHeight, kDepth};
|
||||||
|
|
||||||
|
for (unsigned int i = 1; i < 6; ++i) {
|
||||||
|
TextureSpec textureSpec = defaultTextureSpec;
|
||||||
|
textureSpec.copyLevel = i;
|
||||||
|
textureSpec.levelCount = i + 1;
|
||||||
|
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth >> i, kHeight >> i, kDepth >> i),
|
||||||
|
{kWidth >> i, kHeight >> i, kDepth >> i}, wgpu::TextureDimension::e3D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(yunchao.he@intel.com): add T2B tests for 3D textures, like RowPitch,
|
// TODO(yunchao.he@intel.com): add T2B tests for 3D textures, like RowPitch,
|
||||||
// RowsPerImage, buffer offset, partial depth range, non-zero level, etc.
|
// RowsPerImage, buffer offset, partial depth range, non-zero level, etc.
|
||||||
|
|
||||||
|
@ -1740,6 +1778,44 @@ TEST_P(CopyTests_B2T, Texture3DCopyHeightIsOneCopyWidthIsSmall) {
|
||||||
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kDepth}, wgpu::TextureDimension::e3D);
|
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kDepth}, wgpu::TextureDimension::e3D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that copying texture 3D array mips with 256-byte aligned sizes works
|
||||||
|
TEST_P(CopyTests_B2T, Texture3DMipAligned) {
|
||||||
|
constexpr uint32_t kWidth = 256;
|
||||||
|
constexpr uint32_t kHeight = 128;
|
||||||
|
constexpr uint32_t kDepth = 64u;
|
||||||
|
|
||||||
|
TextureSpec defaultTextureSpec;
|
||||||
|
defaultTextureSpec.textureSize = {kWidth, kHeight, kDepth};
|
||||||
|
|
||||||
|
for (unsigned int i = 1; i < 6; ++i) {
|
||||||
|
TextureSpec textureSpec = defaultTextureSpec;
|
||||||
|
textureSpec.copyLevel = i;
|
||||||
|
textureSpec.levelCount = i + 1;
|
||||||
|
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth >> i, kHeight >> i, kDepth >> i),
|
||||||
|
{kWidth >> i, kHeight >> i, kDepth >> i}, wgpu::TextureDimension::e3D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that copying texture 3D array mips with 256-byte unaligned sizes works
|
||||||
|
TEST_P(CopyTests_B2T, Texture3DMipUnaligned) {
|
||||||
|
constexpr uint32_t kWidth = 261;
|
||||||
|
constexpr uint32_t kHeight = 123;
|
||||||
|
constexpr uint32_t kDepth = 69u;
|
||||||
|
|
||||||
|
TextureSpec defaultTextureSpec;
|
||||||
|
defaultTextureSpec.textureSize = {kWidth, kHeight, kDepth};
|
||||||
|
|
||||||
|
for (unsigned int i = 1; i < 6; ++i) {
|
||||||
|
TextureSpec textureSpec = defaultTextureSpec;
|
||||||
|
textureSpec.copyLevel = i;
|
||||||
|
textureSpec.levelCount = i + 1;
|
||||||
|
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth >> i, kHeight >> i, kDepth >> i),
|
||||||
|
{kWidth >> i, kHeight >> i, kDepth >> i}, wgpu::TextureDimension::e3D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(yunchao.he@intel.com): add more tests like RowPitch, RowsPerImage, buffer offset, partial
|
// TODO(yunchao.he@intel.com): add more tests like RowPitch, RowsPerImage, buffer offset, partial
|
||||||
// depth range, non-zero level, etc.
|
// depth range, non-zero level, etc.
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,7 @@ class CopyTextureForBrowserTests : public DawnTest {
|
||||||
wgpu::Texture srcTexture = device.CreateTexture(&srcDescriptor);
|
wgpu::Texture srcTexture = device.CreateTexture(&srcDescriptor);
|
||||||
|
|
||||||
const utils::TextureDataCopyLayout srcCopyLayout =
|
const utils::TextureDataCopyLayout srcCopyLayout =
|
||||||
utils::GetTextureDataCopyLayoutForTexture2DAtLevel(
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
||||||
kTextureFormat,
|
kTextureFormat,
|
||||||
{srcSpec.textureSize.width, srcSpec.textureSize.height,
|
{srcSpec.textureSize.width, srcSpec.textureSize.height,
|
||||||
copySize.depthOrArrayLayers},
|
copySize.depthOrArrayLayers},
|
||||||
|
@ -293,7 +293,7 @@ class CopyTextureForBrowserTests : public DawnTest {
|
||||||
if (testSubRectCopy) {
|
if (testSubRectCopy) {
|
||||||
// For subrect copy tests, dst texture use kTextureFormat always.
|
// For subrect copy tests, dst texture use kTextureFormat always.
|
||||||
const utils::TextureDataCopyLayout dstCopyLayout =
|
const utils::TextureDataCopyLayout dstCopyLayout =
|
||||||
utils::GetTextureDataCopyLayoutForTexture2DAtLevel(
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
||||||
kTextureFormat,
|
kTextureFormat,
|
||||||
{dstSpec.textureSize.width, dstSpec.textureSize.height,
|
{dstSpec.textureSize.width, dstSpec.textureSize.height,
|
||||||
copySize.depthOrArrayLayers},
|
copySize.depthOrArrayLayers},
|
||||||
|
|
|
@ -31,10 +31,11 @@ namespace utils {
|
||||||
return Align(bytesPerBlock * (width / blockWidth), kTextureBytesPerRowAlignment);
|
return Align(bytesPerBlock * (width / blockWidth), kTextureBytesPerRowAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel(
|
TextureDataCopyLayout GetTextureDataCopyLayoutForTextureAtLevel(
|
||||||
wgpu::TextureFormat format,
|
wgpu::TextureFormat format,
|
||||||
wgpu::Extent3D textureSizeAtLevel0,
|
wgpu::Extent3D textureSizeAtLevel0,
|
||||||
uint32_t mipmapLevel,
|
uint32_t mipmapLevel,
|
||||||
|
wgpu::TextureDimension dimension,
|
||||||
uint32_t rowsPerImage) {
|
uint32_t rowsPerImage) {
|
||||||
// Compressed texture formats not supported in this function yet.
|
// Compressed texture formats not supported in this function yet.
|
||||||
ASSERT(utils::GetTextureFormatBlockWidth(format) == 1);
|
ASSERT(utils::GetTextureFormatBlockWidth(format) == 1);
|
||||||
|
@ -45,6 +46,11 @@ namespace utils {
|
||||||
std::max(textureSizeAtLevel0.height >> mipmapLevel, 1u),
|
std::max(textureSizeAtLevel0.height >> mipmapLevel, 1u),
|
||||||
textureSizeAtLevel0.depthOrArrayLayers};
|
textureSizeAtLevel0.depthOrArrayLayers};
|
||||||
|
|
||||||
|
if (dimension == wgpu::TextureDimension::e3D) {
|
||||||
|
layout.mipSize.depthOrArrayLayers =
|
||||||
|
std::max(textureSizeAtLevel0.depthOrArrayLayers >> mipmapLevel, 1u);
|
||||||
|
}
|
||||||
|
|
||||||
layout.bytesPerRow = GetMinimumBytesPerRow(format, layout.mipSize.width);
|
layout.bytesPerRow = GetMinimumBytesPerRow(format, layout.mipSize.width);
|
||||||
|
|
||||||
if (rowsPerImage == wgpu::kCopyStrideUndefined) {
|
if (rowsPerImage == wgpu::kCopyStrideUndefined) {
|
||||||
|
|
|
@ -31,10 +31,11 @@ namespace utils {
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width);
|
uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width);
|
||||||
TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel(
|
TextureDataCopyLayout GetTextureDataCopyLayoutForTextureAtLevel(
|
||||||
wgpu::TextureFormat format,
|
wgpu::TextureFormat format,
|
||||||
wgpu::Extent3D textureSizeAtLevel0,
|
wgpu::Extent3D textureSizeAtLevel0,
|
||||||
uint32_t mipmapLevel,
|
uint32_t mipmapLevel,
|
||||||
|
wgpu::TextureDimension dimension = wgpu::TextureDimension::e2D,
|
||||||
uint32_t rowsPerImage = wgpu::kCopyStrideUndefined);
|
uint32_t rowsPerImage = wgpu::kCopyStrideUndefined);
|
||||||
|
|
||||||
uint64_t RequiredBytesInCopy(uint64_t bytesPerRow,
|
uint64_t RequiredBytesInCopy(uint64_t bytesPerRow,
|
||||||
|
|
Loading…
Reference in New Issue