Add texture aspect to texture copy view and validation tests
Bug: dawn:439 Change-Id: I0ca283f58fe2b63ac3a8c468f8ea1bb2d300856f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24683 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
b8a56af176
commit
0d9fce100d
|
@ -1592,7 +1592,8 @@
|
|||
{"name": "texture", "type": "texture"},
|
||||
{"name": "mip level", "type": "uint32_t", "default": "0"},
|
||||
{"name": "array layer", "type": "uint32_t", "default": "0"},
|
||||
{"name": "origin", "type": "origin 3D"}
|
||||
{"name": "origin", "type": "origin 3D"},
|
||||
{"name": "aspect", "type": "texture aspect", "default": "all"}
|
||||
]
|
||||
},
|
||||
"texture data layout": {
|
||||
|
|
|
@ -100,6 +100,12 @@ namespace dawn_native {
|
|||
return DAWN_VALIDATION_ERROR("Source and destination texture formats must match.");
|
||||
}
|
||||
|
||||
if (src.aspect != wgpu::TextureAspect::All || dst.aspect != wgpu::TextureAspect::All) {
|
||||
// Metal cannot select a single aspect for texture-to-texture copies
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"Texture aspect must be \"all\" for texture to texture copies");
|
||||
}
|
||||
|
||||
if (src.texture->GetFormat().HasDepthOrStencil()) {
|
||||
// D3D12 requires entire subresource to be copied when using CopyTextureRegion is
|
||||
// used with depth/stencil.
|
||||
|
@ -119,6 +125,55 @@ namespace dawn_native {
|
|||
return {};
|
||||
}
|
||||
|
||||
MaybeError ValidateTextureToBufferCopyRestrictions(const TextureCopyView& src) {
|
||||
const Format& format = src.texture->GetFormat();
|
||||
|
||||
bool depthSelected = false;
|
||||
switch (src.aspect) {
|
||||
case wgpu::TextureAspect::All:
|
||||
switch (format.aspects) {
|
||||
case Aspect::Color:
|
||||
case Aspect::Stencil:
|
||||
break;
|
||||
case Aspect::Depth:
|
||||
depthSelected = true;
|
||||
break;
|
||||
default:
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"A single aspect must be selected for multi planar formats in "
|
||||
"texture to buffer copies");
|
||||
}
|
||||
break;
|
||||
case wgpu::TextureAspect::DepthOnly:
|
||||
ASSERT(format.aspects & Aspect::Depth);
|
||||
depthSelected = true;
|
||||
break;
|
||||
case wgpu::TextureAspect::StencilOnly:
|
||||
ASSERT(format.aspects & Aspect::Stencil);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (depthSelected) {
|
||||
switch (format.format) {
|
||||
case wgpu::TextureFormat::Depth24Plus:
|
||||
case wgpu::TextureFormat::Depth24PlusStencil8:
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"The depth aspect of depth24plus texture cannot be selected in a "
|
||||
"texture to buffer copy");
|
||||
break;
|
||||
case wgpu::TextureFormat::Depth32Float:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage) {
|
||||
ASSERT(wgpu::HasZeroOrOneBits(usage));
|
||||
if (!(buffer->GetUsage() & usage)) {
|
||||
|
@ -661,8 +716,11 @@ namespace dawn_native {
|
|||
// copyExtent.height by blockHeight while the divisibility conditions are
|
||||
// checked in validating texture copy range.
|
||||
DAWN_TRY(ValidateTextureCopyRange(*destination, *copySize));
|
||||
DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(),
|
||||
destination->texture->GetFormat(), *copySize));
|
||||
DAWN_TRY(ValidateBufferToTextureCopyRestrictions(*destination));
|
||||
DAWN_TRY(ValidateLinearTextureData(
|
||||
source->layout, source->buffer->GetSize(),
|
||||
destination->texture->GetFormat().GetTexelBlockInfo(destination->aspect),
|
||||
*copySize));
|
||||
|
||||
mTopLevelBuffers.insert(source->buffer);
|
||||
mTopLevelTextures.insert(destination->texture);
|
||||
|
@ -718,9 +776,10 @@ namespace dawn_native {
|
|||
// copyExtent.height by blockHeight while the divisibility conditions are
|
||||
// checked in validating texture copy range.
|
||||
DAWN_TRY(ValidateTextureCopyRange(*source, *copySize));
|
||||
DAWN_TRY(ValidateLinearTextureData(destination->layout,
|
||||
destination->buffer->GetSize(),
|
||||
source->texture->GetFormat(), *copySize));
|
||||
DAWN_TRY(ValidateTextureToBufferCopyRestrictions(*source));
|
||||
DAWN_TRY(ValidateLinearTextureData(
|
||||
destination->layout, destination->buffer->GetSize(),
|
||||
source->texture->GetFormat().GetTexelBlockInfo(source->aspect), *copySize));
|
||||
|
||||
mTopLevelTextures.insert(source->texture);
|
||||
mTopLevelBuffers.insert(destination->buffer);
|
||||
|
|
|
@ -370,7 +370,7 @@ namespace dawn_native {
|
|||
static_cast<uint64_t>(maxStart);
|
||||
}
|
||||
|
||||
uint32_t ComputeRequiredBytesInCopy(const Format& textureFormat,
|
||||
uint32_t ComputeRequiredBytesInCopy(const TexelBlockInfo& blockInfo,
|
||||
const Extent3D& copySize,
|
||||
uint32_t bytesPerRow,
|
||||
uint32_t rowsPerImage) {
|
||||
|
@ -386,11 +386,11 @@ namespace dawn_native {
|
|||
ASSERT(copySize.height >= 1);
|
||||
ASSERT(copySize.depth >= 1);
|
||||
|
||||
uint64_t texelBlockRowsPerImage = rowsPerImage / textureFormat.blockHeight;
|
||||
uint64_t texelBlockRowsPerImage = rowsPerImage / blockInfo.blockHeight;
|
||||
uint64_t bytesPerImage = bytesPerRow * texelBlockRowsPerImage;
|
||||
uint64_t bytesInLastSlice =
|
||||
bytesPerRow * (copySize.height / textureFormat.blockHeight - 1) +
|
||||
(copySize.width / textureFormat.blockWidth * textureFormat.blockByteSize);
|
||||
bytesPerRow * (copySize.height / blockInfo.blockHeight - 1) +
|
||||
(copySize.width / blockInfo.blockWidth * blockInfo.blockByteSize);
|
||||
return bytesPerImage * (copySize.depth - 1) + bytesInLastSlice;
|
||||
}
|
||||
|
||||
|
@ -408,15 +408,15 @@ namespace dawn_native {
|
|||
|
||||
MaybeError ValidateLinearTextureData(const TextureDataLayout& layout,
|
||||
uint64_t byteSize,
|
||||
const Format& format,
|
||||
const TexelBlockInfo& blockInfo,
|
||||
const Extent3D& copyExtent) {
|
||||
// Validation for the texel block alignments:
|
||||
if (layout.rowsPerImage % format.blockHeight != 0) {
|
||||
if (layout.rowsPerImage % blockInfo.blockHeight != 0) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"rowsPerImage must be a multiple of compressed texture format block height");
|
||||
}
|
||||
|
||||
if (layout.offset % format.blockByteSize != 0) {
|
||||
if (layout.offset % blockInfo.blockByteSize != 0) {
|
||||
return DAWN_VALIDATION_ERROR("Offset must be a multiple of the texel or block size");
|
||||
}
|
||||
|
||||
|
@ -429,8 +429,8 @@ namespace dawn_native {
|
|||
// because the divisibility conditions are necessary for the algorithm to be valid.
|
||||
// TODO(tommek@google.com): to match the spec this should only be checked when
|
||||
// copyExtent.depth > 1.
|
||||
uint32_t requiredBytesInCopy =
|
||||
ComputeRequiredBytesInCopy(format, copyExtent, layout.bytesPerRow, layout.rowsPerImage);
|
||||
uint32_t requiredBytesInCopy = ComputeRequiredBytesInCopy(
|
||||
blockInfo, copyExtent, layout.bytesPerRow, layout.rowsPerImage);
|
||||
|
||||
bool fitsInData =
|
||||
layout.offset <= byteSize && (requiredBytesInCopy <= (byteSize - layout.offset));
|
||||
|
@ -440,7 +440,8 @@ namespace dawn_native {
|
|||
}
|
||||
|
||||
// Validation for other members in layout:
|
||||
if (layout.bytesPerRow < copyExtent.width / format.blockWidth * format.blockByteSize) {
|
||||
if (layout.bytesPerRow <
|
||||
copyExtent.width / blockInfo.blockWidth * blockInfo.blockByteSize) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"bytesPerRow must not be less than the number of bytes per row");
|
||||
}
|
||||
|
@ -482,6 +483,26 @@ namespace dawn_native {
|
|||
"Offset.y must be a multiple of compressed texture format block height");
|
||||
}
|
||||
|
||||
switch (textureCopy.aspect) {
|
||||
case wgpu::TextureAspect::All:
|
||||
break;
|
||||
case wgpu::TextureAspect::DepthOnly:
|
||||
if ((textureCopy.texture->GetFormat().aspects & Aspect::Depth) == 0) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"Texture does not have depth aspect for texture copy");
|
||||
}
|
||||
break;
|
||||
case wgpu::TextureAspect::StencilOnly:
|
||||
if ((textureCopy.texture->GetFormat().aspects & Aspect::Stencil) == 0) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"Texture does not have stencil aspect for texture copy");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -523,4 +544,37 @@ namespace dawn_native {
|
|||
return {};
|
||||
}
|
||||
|
||||
MaybeError ValidateBufferToTextureCopyRestrictions(const TextureCopyView& dst) {
|
||||
const Format& format = dst.texture->GetFormat();
|
||||
|
||||
bool depthSelected = false;
|
||||
switch (dst.aspect) {
|
||||
case wgpu::TextureAspect::All:
|
||||
switch (format.aspects) {
|
||||
case Aspect::Color:
|
||||
case Aspect::Stencil:
|
||||
break;
|
||||
case Aspect::Depth:
|
||||
depthSelected = true;
|
||||
break;
|
||||
default:
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"A single aspect must be selected for multi planar formats in buffer "
|
||||
"to texture copies");
|
||||
}
|
||||
break;
|
||||
case wgpu::TextureAspect::DepthOnly:
|
||||
ASSERT(format.aspects & Aspect::Depth);
|
||||
depthSelected = true;
|
||||
break;
|
||||
case wgpu::TextureAspect::StencilOnly:
|
||||
ASSERT(format.aspects & Aspect::Stencil);
|
||||
break;
|
||||
}
|
||||
if (depthSelected) {
|
||||
return DAWN_VALIDATION_ERROR("Cannot copy into the depth aspect of a texture");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace dawn_native {
|
|||
class QuerySetBase;
|
||||
struct BeginRenderPassCmd;
|
||||
struct PassResourceUsage;
|
||||
struct TexelBlockInfo;
|
||||
|
||||
MaybeError ValidateCanPopDebugGroup(uint64_t debugGroupStackSize);
|
||||
MaybeError ValidateFinalDebugGroupStackSize(uint64_t debugGroupStackSize);
|
||||
|
@ -40,17 +41,18 @@ namespace dawn_native {
|
|||
|
||||
MaybeError ValidateTimestampQuery(QuerySetBase* querySet, uint32_t queryIndex);
|
||||
|
||||
uint32_t ComputeRequiredBytesInCopy(const Format& textureFormat,
|
||||
uint32_t ComputeRequiredBytesInCopy(const TexelBlockInfo& blockInfo,
|
||||
const Extent3D& copySize,
|
||||
uint32_t bytesPerRow,
|
||||
uint32_t rowsPerImage);
|
||||
|
||||
MaybeError ValidateLinearTextureData(const TextureDataLayout& layout,
|
||||
uint64_t byteSize,
|
||||
const Format& format,
|
||||
const TexelBlockInfo& blockInfo,
|
||||
const Extent3D& copyExtent);
|
||||
MaybeError ValidateTextureCopyRange(const TextureCopyView& textureCopyView,
|
||||
const Extent3D& copySize);
|
||||
MaybeError ValidateBufferToTextureCopyRestrictions(const TextureCopyView& dst);
|
||||
|
||||
MaybeError ValidateBufferCopyView(DeviceBase const* device,
|
||||
const BufferCopyView& bufferCopyView);
|
||||
|
|
|
@ -79,6 +79,47 @@ namespace dawn_native {
|
|||
return componentType == type;
|
||||
}
|
||||
|
||||
TexelBlockInfo Format::GetTexelBlockInfo(wgpu::TextureAspect aspect) const {
|
||||
switch (aspect) {
|
||||
case wgpu::TextureAspect::All:
|
||||
switch (aspects) {
|
||||
case Aspect::Color:
|
||||
case Aspect::Depth:
|
||||
case Aspect::Stencil:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return *this;
|
||||
|
||||
case wgpu::TextureAspect::DepthOnly:
|
||||
ASSERT(HasDepth());
|
||||
switch (format) {
|
||||
case wgpu::TextureFormat::Depth32Float:
|
||||
return *this;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case wgpu::TextureAspect::StencilOnly:
|
||||
ASSERT(HasStencil());
|
||||
switch (format) {
|
||||
case wgpu::TextureFormat::Depth24PlusStencil8:
|
||||
return {1, 1, 1};
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t Format::GetIndex() const {
|
||||
return ComputeFormatIndex(format);
|
||||
}
|
||||
|
|
|
@ -29,12 +29,18 @@ namespace dawn_native {
|
|||
enum class Aspect : uint8_t;
|
||||
class DeviceBase;
|
||||
|
||||
struct TexelBlockInfo {
|
||||
uint32_t blockByteSize;
|
||||
uint32_t blockWidth;
|
||||
uint32_t blockHeight;
|
||||
};
|
||||
|
||||
// The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
|
||||
// exact number of known format.
|
||||
static constexpr size_t kKnownFormatCount = 52;
|
||||
|
||||
// A wgpu::TextureFormat along with all the information about it necessary for validation.
|
||||
struct Format {
|
||||
struct Format : TexelBlockInfo {
|
||||
enum class Type {
|
||||
Float,
|
||||
Sint,
|
||||
|
@ -51,10 +57,6 @@ namespace dawn_native {
|
|||
Type type;
|
||||
Aspect aspects;
|
||||
|
||||
uint32_t blockByteSize;
|
||||
uint32_t blockWidth;
|
||||
uint32_t blockHeight;
|
||||
|
||||
static Type TextureComponentTypeToFormatType(wgpu::TextureComponentType componentType);
|
||||
static wgpu::TextureComponentType FormatTypeToTextureComponentType(Type type);
|
||||
|
||||
|
@ -64,6 +66,8 @@ namespace dawn_native {
|
|||
bool HasDepthOrStencil() const;
|
||||
bool HasComponentType(Type componentType) const;
|
||||
|
||||
TexelBlockInfo GetTexelBlockInfo(wgpu::TextureAspect aspect) const;
|
||||
|
||||
// The index of the format in the list of all known formats: a unique number for each format
|
||||
// in [0, kKnownFormatCount)
|
||||
size_t GetIndex() const;
|
||||
|
|
|
@ -275,8 +275,10 @@ namespace dawn_native {
|
|||
// copyExtent.height by blockHeight while the divisibility conditions are
|
||||
// checked in validating texture copy range.
|
||||
DAWN_TRY(ValidateTextureCopyRange(*destination, *writeSize));
|
||||
DAWN_TRY(ValidateLinearTextureData(*dataLayout, dataSize, destination->texture->GetFormat(),
|
||||
*writeSize));
|
||||
DAWN_TRY(ValidateBufferToTextureCopyRestrictions(*destination));
|
||||
DAWN_TRY(ValidateLinearTextureData(
|
||||
*dataLayout, dataSize,
|
||||
destination->texture->GetFormat().GetTexelBlockInfo(destination->aspect), *writeSize));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -75,11 +75,12 @@ class CopyCommandTest : public ValidationTest {
|
|||
wgpu::Texture destTexture,
|
||||
uint32_t destLevel,
|
||||
wgpu::Origin3D destOrigin,
|
||||
wgpu::Extent3D extent3D) {
|
||||
wgpu::Extent3D extent3D,
|
||||
wgpu::TextureAspect aspect = wgpu::TextureAspect::All) {
|
||||
wgpu::BufferCopyView bufferCopyView =
|
||||
utils::CreateBufferCopyView(srcBuffer, srcOffset, srcBytesPerRow, srcRowsPerImage);
|
||||
wgpu::TextureCopyView textureCopyView =
|
||||
utils::CreateTextureCopyView(destTexture, destLevel, destOrigin);
|
||||
utils::CreateTextureCopyView(destTexture, destLevel, destOrigin, aspect);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &extent3D);
|
||||
|
@ -95,11 +96,12 @@ class CopyCommandTest : public ValidationTest {
|
|||
uint64_t destOffset,
|
||||
uint32_t destBytesPerRow,
|
||||
uint32_t destRowsPerImage,
|
||||
wgpu::Extent3D extent3D) {
|
||||
wgpu::Extent3D extent3D,
|
||||
wgpu::TextureAspect aspect = wgpu::TextureAspect::All) {
|
||||
wgpu::BufferCopyView bufferCopyView =
|
||||
utils::CreateBufferCopyView(destBuffer, destOffset, destBytesPerRow, destRowsPerImage);
|
||||
wgpu::TextureCopyView textureCopyView =
|
||||
utils::CreateTextureCopyView(srcTexture, srcLevel, srcOrigin);
|
||||
utils::CreateTextureCopyView(srcTexture, srcLevel, srcOrigin, aspect);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, &extent3D);
|
||||
|
@ -114,11 +116,12 @@ class CopyCommandTest : public ValidationTest {
|
|||
wgpu::Texture dstTexture,
|
||||
uint32_t dstLevel,
|
||||
wgpu::Origin3D dstOrigin,
|
||||
wgpu::Extent3D extent3D) {
|
||||
wgpu::Extent3D extent3D,
|
||||
wgpu::TextureAspect aspect = wgpu::TextureAspect::All) {
|
||||
wgpu::TextureCopyView srcTextureCopyView =
|
||||
utils::CreateTextureCopyView(srcTexture, srcLevel, srcOrigin);
|
||||
utils::CreateTextureCopyView(srcTexture, srcLevel, srcOrigin, aspect);
|
||||
wgpu::TextureCopyView dstTextureCopyView =
|
||||
utils::CreateTextureCopyView(dstTexture, dstLevel, dstOrigin);
|
||||
utils::CreateTextureCopyView(dstTexture, dstLevel, dstOrigin, aspect);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyTextureToTexture(&srcTextureCopyView, &dstTextureCopyView, &extent3D);
|
||||
|
@ -682,6 +685,83 @@ TEST_F(CopyCommandTest_B2T, CopyToMipmapOfNonSquareTexture) {
|
|||
{0, 0, 0}, {2, 2, 1});
|
||||
}
|
||||
|
||||
// Test it is invalid to copy to a depth texture
|
||||
TEST_F(CopyCommandTest_B2T, CopyToDepthAspect) {
|
||||
// Test it is invalid to copy from a buffer into Depth32Float
|
||||
{
|
||||
uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1, wgpu::TextureFormat::R32Float);
|
||||
wgpu::Buffer source = CreateBuffer(bufferSize, wgpu::BufferUsage::CopySrc);
|
||||
|
||||
wgpu::Texture destination = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::Depth32Float,
|
||||
wgpu::TextureUsage::CopyDst);
|
||||
|
||||
TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 0, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::All);
|
||||
|
||||
TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 0, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::DepthOnly);
|
||||
}
|
||||
|
||||
// Test it is invalid to copy from a buffer into Depth24Plus
|
||||
{
|
||||
uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1, wgpu::TextureFormat::R32Float);
|
||||
wgpu::Buffer source = CreateBuffer(bufferSize, wgpu::BufferUsage::CopySrc);
|
||||
|
||||
wgpu::Texture destination = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::Depth24Plus,
|
||||
wgpu::TextureUsage::CopyDst);
|
||||
|
||||
TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 0, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::All);
|
||||
|
||||
TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 0, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::DepthOnly);
|
||||
}
|
||||
}
|
||||
|
||||
// Test copy to only the stencil aspect of a texture
|
||||
TEST_F(CopyCommandTest_B2T, CopyToStencilAspect) {
|
||||
// Test it is valid to copy from a buffer into the stencil aspect of Depth24PlusStencil8
|
||||
{
|
||||
uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1, wgpu::TextureFormat::R8Uint);
|
||||
wgpu::Buffer source = CreateBuffer(bufferSize, wgpu::BufferUsage::CopySrc);
|
||||
|
||||
wgpu::Texture destination = Create2DTexture(
|
||||
16, 16, 1, 1, wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureUsage::CopyDst);
|
||||
|
||||
TestB2TCopy(utils::Expectation::Success, source, 0, 256, 0, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::StencilOnly);
|
||||
|
||||
// And that it fails if the buffer is one byte too small
|
||||
wgpu::Buffer sourceSmall = CreateBuffer(bufferSize - 1, wgpu::BufferUsage::CopySrc);
|
||||
TestB2TCopy(utils::Expectation::Failure, sourceSmall, 0, 256, 0, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::StencilOnly);
|
||||
}
|
||||
|
||||
// Test it is invalid to copy from a buffer into the stencil aspect of Depth24Plus (no stencil)
|
||||
{
|
||||
uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1, wgpu::TextureFormat::R8Uint);
|
||||
wgpu::Buffer source = CreateBuffer(bufferSize, wgpu::BufferUsage::CopySrc);
|
||||
|
||||
wgpu::Texture destination = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::Depth24Plus,
|
||||
wgpu::TextureUsage::CopyDst);
|
||||
|
||||
TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 0, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::StencilOnly);
|
||||
}
|
||||
|
||||
// Test it is invalid to copy from a buffer into the stencil aspect of a color texture
|
||||
{
|
||||
uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1, wgpu::TextureFormat::R8Uint);
|
||||
wgpu::Buffer source = CreateBuffer(bufferSize, wgpu::BufferUsage::CopySrc);
|
||||
|
||||
wgpu::Texture destination = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Uint,
|
||||
wgpu::TextureUsage::CopyDst);
|
||||
|
||||
TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 0, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::StencilOnly);
|
||||
}
|
||||
}
|
||||
|
||||
class CopyCommandTest_T2B : public CopyCommandTest {};
|
||||
|
||||
// Test a successfull T2B copy
|
||||
|
@ -1010,6 +1090,83 @@ TEST_F(CopyCommandTest_T2B, CopyFromMipmapOfNonSquareTexture) {
|
|||
256, 0, {2, 1, 1});
|
||||
}
|
||||
|
||||
// Test copy from only the depth aspect of a texture
|
||||
TEST_F(CopyCommandTest_T2B, CopyFromDepthAspect) {
|
||||
uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1, wgpu::TextureFormat::R32Float);
|
||||
wgpu::Buffer destination = CreateBuffer(bufferSize, wgpu::BufferUsage::CopyDst);
|
||||
{
|
||||
wgpu::Texture source = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::Depth32Float,
|
||||
wgpu::TextureUsage::CopySrc);
|
||||
|
||||
// Test "all" of a depth texture which is only the depth aspect.
|
||||
TestT2BCopy(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0, 256, 0,
|
||||
{16, 16, 1}, wgpu::TextureAspect::All);
|
||||
|
||||
// Test it is valid to copy the depth aspect of a depth texture
|
||||
TestT2BCopy(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0, 256, 0,
|
||||
{16, 16, 1}, wgpu::TextureAspect::DepthOnly);
|
||||
}
|
||||
{
|
||||
wgpu::Texture source = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::Depth24Plus,
|
||||
wgpu::TextureUsage::CopySrc);
|
||||
|
||||
// Test it is invalid to copy from the depth aspect of depth24plus
|
||||
TestT2BCopy(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0, 256, 0,
|
||||
{16, 16, 1}, wgpu::TextureAspect::DepthOnly);
|
||||
}
|
||||
{
|
||||
wgpu::Texture source = Create2DTexture(
|
||||
16, 16, 1, 1, wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureUsage::CopySrc);
|
||||
|
||||
// Test it is invalid to copy from the depth aspect of depth24plus-stencil8
|
||||
TestT2BCopy(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0, 256, 0,
|
||||
{16, 16, 1}, wgpu::TextureAspect::DepthOnly);
|
||||
}
|
||||
{
|
||||
wgpu::Texture source = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::R32Float,
|
||||
wgpu::TextureUsage::CopySrc);
|
||||
|
||||
// Test it is invalid to copy from the depth aspect of a color texture
|
||||
TestT2BCopy(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0, 256, 0,
|
||||
{16, 16, 1}, wgpu::TextureAspect::DepthOnly);
|
||||
}
|
||||
}
|
||||
|
||||
// Test copy from only the stencil aspect of a texture
|
||||
TEST_F(CopyCommandTest_T2B, CopyFromStencilAspect) {
|
||||
uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1, wgpu::TextureFormat::R8Uint);
|
||||
wgpu::Buffer destination = CreateBuffer(bufferSize, wgpu::BufferUsage::CopyDst);
|
||||
{
|
||||
wgpu::Texture source = Create2DTexture(
|
||||
16, 16, 1, 1, wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureUsage::CopySrc);
|
||||
|
||||
// Test it is valid to copy from the stencil aspect of a depth24plus-stencil8 texture
|
||||
TestT2BCopy(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0, 256, 0,
|
||||
{16, 16, 1}, wgpu::TextureAspect::StencilOnly);
|
||||
|
||||
// Test it is invalid if the buffer is too small
|
||||
wgpu::Buffer destinationSmall = CreateBuffer(bufferSize - 1, wgpu::BufferUsage::CopyDst);
|
||||
TestT2BCopy(utils::Expectation::Failure, source, 0, {0, 0, 0}, destinationSmall, 0, 256, 0,
|
||||
{16, 16, 1}, wgpu::TextureAspect::StencilOnly);
|
||||
}
|
||||
{
|
||||
wgpu::Texture source =
|
||||
Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::R8Uint, wgpu::TextureUsage::CopySrc);
|
||||
|
||||
// Test it is invalid to copy from the stencil aspect of a color texture
|
||||
TestT2BCopy(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0, 256, 0,
|
||||
{16, 16, 1}, wgpu::TextureAspect::StencilOnly);
|
||||
}
|
||||
{
|
||||
wgpu::Texture source = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::Depth24Plus,
|
||||
wgpu::TextureUsage::CopySrc);
|
||||
|
||||
// Test it is invalid to copy from the stencil aspect of a depth-only texture
|
||||
TestT2BCopy(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0, 256, 0,
|
||||
{16, 16, 1}, wgpu::TextureAspect::StencilOnly);
|
||||
}
|
||||
}
|
||||
|
||||
class CopyCommandTest_T2T : public CopyCommandTest {};
|
||||
|
||||
TEST_F(CopyCommandTest_T2T, Success) {
|
||||
|
@ -1164,6 +1321,14 @@ TEST_F(CopyCommandTest_T2T, 2DTextureDepthStencil) {
|
|||
// Failure when depth stencil subresource is partially copied
|
||||
TestT2TCopy(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0, {0, 0, 0},
|
||||
{15, 15, 1});
|
||||
|
||||
// Failure when selecting the depth aspect (not all)
|
||||
TestT2TCopy(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::DepthOnly);
|
||||
|
||||
// Failure when selecting the stencil aspect (not all)
|
||||
TestT2TCopy(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0, {0, 0, 0},
|
||||
{16, 16, 1}, wgpu::TextureAspect::StencilOnly);
|
||||
}
|
||||
|
||||
TEST_F(CopyCommandTest_T2T, 2DTextureArrayDepthStencil) {
|
||||
|
|
|
@ -53,7 +53,8 @@ namespace {
|
|||
wgpu::Texture texture,
|
||||
uint32_t texLevel,
|
||||
wgpu::Origin3D texOrigin,
|
||||
wgpu::Extent3D size) {
|
||||
wgpu::Extent3D size,
|
||||
wgpu::TextureAspect aspect = wgpu::TextureAspect::All) {
|
||||
std::vector<uint8_t> data(dataSize);
|
||||
|
||||
wgpu::TextureDataLayout textureDataLayout;
|
||||
|
@ -62,7 +63,7 @@ namespace {
|
|||
textureDataLayout.rowsPerImage = dataRowsPerImage;
|
||||
|
||||
wgpu::TextureCopyView textureCopyView =
|
||||
utils::CreateTextureCopyView(texture, texLevel, texOrigin);
|
||||
utils::CreateTextureCopyView(texture, texLevel, texOrigin, aspect);
|
||||
|
||||
queue.WriteTexture(&textureCopyView, data.data(), dataSize, &textureDataLayout, &size);
|
||||
}
|
||||
|
@ -402,6 +403,71 @@ namespace {
|
|||
{0, 0, 1}, {4, 2, 3});
|
||||
}
|
||||
|
||||
// Test it is invalid to write into a depth texture.
|
||||
TEST_F(QueueWriteTextureValidationTest, WriteToDepthAspect) {
|
||||
uint32_t bytesPerRow = sizeof(float) * 4;
|
||||
const uint64_t dataSize = utils::RequiredBytesInCopy(bytesPerRow, 0, {4, 4, 1},
|
||||
wgpu::TextureFormat::Depth32Float);
|
||||
|
||||
// Invalid to write into depth32float
|
||||
{
|
||||
wgpu::Texture destination = QueueWriteTextureValidationTest::Create2DTexture(
|
||||
{4, 4, 1}, 1, wgpu::TextureFormat::Depth32Float, wgpu::TextureUsage::CopyDst);
|
||||
|
||||
ASSERT_DEVICE_ERROR(TestWriteTexture(dataSize, 0, bytesPerRow, 0, destination, 0,
|
||||
{0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All));
|
||||
|
||||
ASSERT_DEVICE_ERROR(TestWriteTexture(dataSize, 0, bytesPerRow, 0, destination, 0,
|
||||
{0, 0, 0}, {4, 4, 1},
|
||||
wgpu::TextureAspect::DepthOnly));
|
||||
}
|
||||
|
||||
// Invalid to write into depth24plus
|
||||
{
|
||||
wgpu::Texture destination = QueueWriteTextureValidationTest::Create2DTexture(
|
||||
{4, 4, 1}, 1, wgpu::TextureFormat::Depth24Plus, wgpu::TextureUsage::CopyDst);
|
||||
|
||||
ASSERT_DEVICE_ERROR(TestWriteTexture(dataSize, 0, bytesPerRow, 0, destination, 0,
|
||||
{0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All));
|
||||
|
||||
ASSERT_DEVICE_ERROR(TestWriteTexture(dataSize, 0, bytesPerRow, 0, destination, 0,
|
||||
{0, 0, 0}, {4, 4, 1},
|
||||
wgpu::TextureAspect::DepthOnly));
|
||||
}
|
||||
}
|
||||
|
||||
// Test write texture to the stencil aspect
|
||||
TEST_F(QueueWriteTextureValidationTest, WriteToStencilAspect) {
|
||||
uint32_t bytesPerRow = 4;
|
||||
const uint64_t dataSize =
|
||||
utils::RequiredBytesInCopy(bytesPerRow, 0, {4, 4, 1}, wgpu::TextureFormat::R8Uint);
|
||||
|
||||
// It is valid to write into the stencil aspect of depth24plus-stencil8
|
||||
{
|
||||
wgpu::Texture destination = QueueWriteTextureValidationTest::Create2DTexture(
|
||||
{4, 4, 1}, 1, wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
wgpu::TextureUsage::CopyDst);
|
||||
|
||||
TestWriteTexture(dataSize, 0, bytesPerRow, 0, destination, 0, {0, 0, 0}, {4, 4, 1},
|
||||
wgpu::TextureAspect::StencilOnly);
|
||||
|
||||
// And that it fails if the buffer is one byte too small
|
||||
ASSERT_DEVICE_ERROR(TestWriteTexture(dataSize - 1, 0, bytesPerRow, 0, destination, 0,
|
||||
{0, 0, 0}, {4, 4, 1},
|
||||
wgpu::TextureAspect::StencilOnly));
|
||||
}
|
||||
|
||||
// It is invalid to write into the stencil aspect of depth24plus (no stencil)
|
||||
{
|
||||
wgpu::Texture destination = QueueWriteTextureValidationTest::Create2DTexture(
|
||||
{4, 4, 1}, 1, wgpu::TextureFormat::Depth24Plus, wgpu::TextureUsage::CopyDst);
|
||||
|
||||
ASSERT_DEVICE_ERROR(TestWriteTexture(dataSize, 0, bytesPerRow, 0, destination, 0,
|
||||
{0, 0, 0}, {4, 4, 1},
|
||||
wgpu::TextureAspect::StencilOnly));
|
||||
}
|
||||
}
|
||||
|
||||
class WriteTextureTest_CompressedTextureFormats : public QueueWriteTextureValidationTest {
|
||||
public:
|
||||
WriteTextureTest_CompressedTextureFormats() : QueueWriteTextureValidationTest() {
|
||||
|
|
|
@ -276,11 +276,13 @@ namespace utils {
|
|||
|
||||
wgpu::TextureCopyView CreateTextureCopyView(wgpu::Texture texture,
|
||||
uint32_t mipLevel,
|
||||
wgpu::Origin3D origin) {
|
||||
wgpu::Origin3D origin,
|
||||
wgpu::TextureAspect aspect) {
|
||||
wgpu::TextureCopyView textureCopyView;
|
||||
textureCopyView.texture = texture;
|
||||
textureCopyView.mipLevel = mipLevel;
|
||||
textureCopyView.origin = origin;
|
||||
textureCopyView.aspect = aspect;
|
||||
|
||||
return textureCopyView;
|
||||
}
|
||||
|
|
|
@ -52,9 +52,11 @@ namespace utils {
|
|||
uint64_t offset,
|
||||
uint32_t bytesPerRow,
|
||||
uint32_t rowsPerImage);
|
||||
wgpu::TextureCopyView CreateTextureCopyView(wgpu::Texture texture,
|
||||
wgpu::TextureCopyView CreateTextureCopyView(
|
||||
wgpu::Texture texture,
|
||||
uint32_t level,
|
||||
wgpu::Origin3D origin);
|
||||
wgpu::Origin3D origin,
|
||||
wgpu::TextureAspect aspect = wgpu::TextureAspect::All);
|
||||
wgpu::TextureDataLayout CreateTextureDataLayout(uint64_t offset,
|
||||
uint32_t bytesPerRow,
|
||||
uint32_t rowsPerImage);
|
||||
|
|
Loading…
Reference in New Issue