summaryrefslogtreecommitdiffstats
path: root/tools/gfx-unit-test
diff options
context:
space:
mode:
authorlucy96chen <47800040+lucy96chen@users.noreply.github.com>2022-03-21 16:56:11 -0700
committerGitHub <noreply@github.com>2022-03-21 16:56:11 -0700
commit91292b8ca80ede633d1c4effaf8b3f5cf2ac3f2b (patch)
tree8482871a0aac4cb939031c65886432a36068bcda /tools/gfx-unit-test
parent2e1a84add57efd9f8a50a88d0569a48ae4b6d834 (diff)
Add additional texture to texture copying tests (#2165)
* Working on finding a better way to do result comparisons in order to accommodate testing different formats and texture types, copying small to large texture currently half broken * All tests except copying into a buffer with an offset working with new code for results comparison, support for most formats WIP * Replaced SubresourceStuff with ValidationTextureData; Added implementation for ValidationTextureFormat::initializeTexel() and changed generateTextureData() to call this * All implemented formats work on D3D12, a few broken for Vulkan * Fixed numerous locations in render-vk.cpp to set aspect masks based on either the format or the provided TextureAspect; All tests except copy to buffer with offset working on new code structure * All texture to texture copying tests work for all non-compressed formats; Test code cleaned up to minimize the amount of stuff needing to be passed between functions * All tests working with all texture types except TextureCube and all non-compressed formats; Temporarily removing test for copying to a buffer at an offset, will likely return in a separate test file * Small cleanup changes * build fixes
Diffstat (limited to 'tools/gfx-unit-test')
-rw-r--r--tools/gfx-unit-test/copy-texture-tests.cpp1135
1 files changed, 959 insertions, 176 deletions
diff --git a/tools/gfx-unit-test/copy-texture-tests.cpp b/tools/gfx-unit-test/copy-texture-tests.cpp
index dec71541f..6b9bced1a 100644
--- a/tools/gfx-unit-test/copy-texture-tests.cpp
+++ b/tools/gfx-unit-test/copy-texture-tests.cpp
@@ -14,43 +14,406 @@ using namespace gfx;
namespace gfx_test
{
+ struct ValidationTextureFormatBase : RefObject
+ {
+ virtual void validateBlocksEqual(const void* actual, const void* expected) = 0;
+
+ virtual void initializeTexel(void* texel, int x, int y, int z, int mipLevel, int arrayLayer) = 0;
+ };
+
+ template <typename T>
+ struct ValidationTextureFormat : ValidationTextureFormatBase
+ {
+ int componentCount;
+
+ ValidationTextureFormat(int componentCount) : componentCount(componentCount) {};
+
+ virtual void validateBlocksEqual(const void* actual, const void* expected) override
+ {
+ auto a = (const T*)actual;
+ auto e = (const T*)expected;
+
+ for (Int i = 0; i < componentCount; ++i)
+ {
+ SLANG_CHECK(a[i] == e[i]);
+ }
+ }
+
+ virtual void initializeTexel(void* texel, int x, int y, int z, int mipLevel, int arrayLayer) override
+ {
+ auto temp = (T*)texel;
+
+ switch (componentCount)
+ {
+ case 1:
+ temp[0] = T(x + y + z + mipLevel + arrayLayer);
+ break;
+ case 2:
+ temp[0] = T(x + z + arrayLayer);
+ temp[1] = T(y + mipLevel);
+ break;
+ case 3:
+ temp[0] = T(x + mipLevel);
+ temp[1] = T(y + arrayLayer);
+ temp[2] = T(z);
+ break;
+ case 4:
+ temp[0] = T(x + arrayLayer);
+ temp[1] = (T)y;
+ temp[2] = (T)z;
+ temp[3] = (T)mipLevel;
+ break;
+ default:
+ assert(!"component count should be no greater than 4");
+ SLANG_CHECK_ABORT(false);
+ }
+ }
+ };
+
+ template <typename T>
+ struct PackedValidationTextureFormat : ValidationTextureFormatBase
+ {
+ int rBits;
+ int gBits;
+ int bBits;
+ int aBits;
+
+ PackedValidationTextureFormat(int rBits, int gBits, int bBits, int aBits)
+ : rBits(rBits), gBits(gBits), bBits(bBits), aBits(aBits) {};
+
+ virtual void validateBlocksEqual(const void* actual, const void* expected) override
+ {
+ T a[4];
+ T e[4];
+ unpackTexel(*(const T*)actual, a);
+ unpackTexel(*(const T*)expected, e);
+
+ for (Int i = 0; i < 4; ++i)
+ {
+ SLANG_CHECK(a[i] == e[i]);
+ }
+ }
+
+ virtual void initializeTexel(void* texel, int x, int y, int z, int mipLevel, int arrayLayer) override
+ {
+ T temp = 0;
+
+ // The only formats which currently use this have either 3 or 4 channels. TODO: BC formats?
+ if (aBits == 0)
+ {
+ temp |= z;
+ temp <<= gBits;
+ temp |= (y + arrayLayer);
+ temp <<= rBits;
+ temp |= (x + mipLevel);
+ }
+ else
+ {
+ temp |= mipLevel;
+ temp <<= bBits;
+ temp |= z;
+ temp <<= gBits;
+ temp |= y;
+ temp <<= rBits;
+ temp |= (x + arrayLayer);
+ }
+
+ *(T*)texel = temp;
+ }
+
+ void unpackTexel(T texel, T* outComponents)
+ {
+ outComponents[0] = texel & ((1 << rBits) - 1);
+ texel >>= rBits;
+
+ outComponents[1] = texel & ((1 << gBits) - 1);
+ texel >>= gBits;
+
+ outComponents[2] = texel & ((1 << bBits) - 1);
+ texel >>= bBits;
+
+ outComponents[3] = texel & ((1 << aBits) - 1);
+ texel >>= aBits;
+
+ //for ()
+ }
+ };
+
+ RefPtr<ValidationTextureFormatBase> getValidationTextureFormat(Format format)
+ {
+ switch (format)
+ {
+ case Format::R32G32B32A32_TYPELESS: return new ValidationTextureFormat<uint32_t>(4);
+ case Format::R32G32B32_TYPELESS: return new ValidationTextureFormat<uint32_t>(3);
+ case Format::R32G32_TYPELESS: return new ValidationTextureFormat<uint32_t>(2);
+ case Format::R32_TYPELESS: return new ValidationTextureFormat<uint32_t>(1);
+
+ case Format::R16G16B16A16_TYPELESS: return new ValidationTextureFormat<uint16_t>(4);
+ case Format::R16G16_TYPELESS: return new ValidationTextureFormat<uint16_t>(2);
+ case Format::R16_TYPELESS: return new ValidationTextureFormat<uint16_t>(1);
+
+ case Format::R8G8B8A8_TYPELESS: return new ValidationTextureFormat<uint8_t>(4);
+ case Format::R8G8_TYPELESS: return new ValidationTextureFormat<uint8_t>(2);
+ case Format::R8_TYPELESS: return new ValidationTextureFormat<uint8_t>(1);
+ case Format::B8G8R8A8_TYPELESS: return new ValidationTextureFormat<uint8_t>(4);
+
+ case Format::R32G32B32A32_FLOAT: return new ValidationTextureFormat<float>(4);
+ case Format::R32G32B32_FLOAT: return new ValidationTextureFormat<float>(3);
+ case Format::R32G32_FLOAT: return new ValidationTextureFormat<float>(2);
+ case Format::R32_FLOAT: return new ValidationTextureFormat<float>(1);
+
+ case Format::R16G16B16A16_FLOAT: return new ValidationTextureFormat<uint16_t>(4);
+ case Format::R16G16_FLOAT: return new ValidationTextureFormat<uint16_t>(2);
+ case Format::R16_FLOAT: return new ValidationTextureFormat<uint16_t>(1);
+
+ case Format::R32G32B32A32_UINT: return new ValidationTextureFormat<uint32_t>(4);
+ case Format::R32G32B32_UINT: return new ValidationTextureFormat<uint32_t>(3);
+ case Format::R32G32_UINT: return new ValidationTextureFormat<uint32_t>(2);
+ case Format::R32_UINT: return new ValidationTextureFormat<uint32_t>(1);
+
+ case Format::R16G16B16A16_UINT: return new ValidationTextureFormat<uint16_t>(4);
+ case Format::R16G16_UINT: return new ValidationTextureFormat<uint16_t>(2);
+ case Format::R16_UINT: return new ValidationTextureFormat<uint16_t>(1);
+
+ case Format::R8G8B8A8_UINT: return new ValidationTextureFormat<uint8_t>(4);
+ case Format::R8G8_UINT: return new ValidationTextureFormat<uint8_t>(2);
+ case Format::R8_UINT: return new ValidationTextureFormat<uint8_t>(1);
+
+ case Format::R32G32B32A32_SINT: return new ValidationTextureFormat<int32_t>(4);
+ case Format::R32G32B32_SINT: return new ValidationTextureFormat<int32_t>(3);
+ case Format::R32G32_SINT: return new ValidationTextureFormat<int32_t>(2);
+ case Format::R32_SINT: return new ValidationTextureFormat<int32_t>(1);
+
+ case Format::R16G16B16A16_SINT: return new ValidationTextureFormat<int16_t>(4);
+ case Format::R16G16_SINT: return new ValidationTextureFormat<int16_t>(2);
+ case Format::R16_SINT: return new ValidationTextureFormat<int16_t>(1);
+
+ case Format::R8G8B8A8_SINT: return new ValidationTextureFormat<int8_t>(4);
+ case Format::R8G8_SINT: return new ValidationTextureFormat<int8_t>(2);
+ case Format::R8_SINT: return new ValidationTextureFormat<int8_t>(1);
+
+ case Format::R16G16B16A16_UNORM: return new ValidationTextureFormat<uint16_t>(4);
+ case Format::R16G16_UNORM: return new ValidationTextureFormat<uint16_t>(2);
+ case Format::R16_UNORM: return new ValidationTextureFormat<uint16_t>(1);
+
+ case Format::R8G8B8A8_UNORM: return new ValidationTextureFormat<uint8_t>(4);
+ case Format::R8G8B8A8_UNORM_SRGB: return new ValidationTextureFormat<uint8_t>(4);
+ case Format::R8G8_UNORM: return new ValidationTextureFormat<uint8_t>(2);
+ case Format::R8_UNORM: return new ValidationTextureFormat<uint8_t>(1);
+ case Format::B8G8R8A8_UNORM: return new ValidationTextureFormat<uint8_t>(4);
+ case Format::B8G8R8A8_UNORM_SRGB: return new ValidationTextureFormat<uint8_t>(4);
+ case Format::B8G8R8X8_UNORM: return new ValidationTextureFormat<uint8_t>(3);
+ case Format::B8G8R8X8_UNORM_SRGB: return new ValidationTextureFormat<uint8_t>(3);
+
+ case Format::R16G16B16A16_SNORM: return new ValidationTextureFormat<int16_t>(4);
+ case Format::R16G16_SNORM: return new ValidationTextureFormat<int16_t>(2);
+ case Format::R16_SNORM: return new ValidationTextureFormat<int16_t>(1);
+
+ case Format::R8G8B8A8_SNORM: return new ValidationTextureFormat<int8_t>(4);
+ case Format::R8G8_SNORM: return new ValidationTextureFormat<int8_t>(2);
+ case Format::R8_SNORM: return new ValidationTextureFormat<int8_t>(1);
+
+ case Format::D32_FLOAT: return new ValidationTextureFormat<float>(1);
+ case Format::D16_UNORM: return new ValidationTextureFormat<uint16_t>(1);
+
+ case Format::B4G4R4A4_UNORM: return new PackedValidationTextureFormat<uint16_t>(4, 4, 4, 4);
+ case Format::B5G6R5_UNORM: return new PackedValidationTextureFormat<uint16_t>(5, 6, 5, 0);
+ case Format::B5G5R5A1_UNORM: return new PackedValidationTextureFormat<uint16_t>(5, 5, 5, 1);
+
+ case Format::R9G9B9E5_SHAREDEXP: return new ValidationTextureFormat<uint32_t>(1);
+ case Format::R10G10B10A2_TYPELESS: return new PackedValidationTextureFormat<uint32_t>(10, 10, 10, 2);
+ case Format::R10G10B10A2_UNORM: return new PackedValidationTextureFormat<uint32_t>(10, 10, 10, 2);
+ case Format::R10G10B10A2_UINT: return new PackedValidationTextureFormat<uint32_t>(10, 10, 10, 2);
+ case Format::R11G11B10_FLOAT: return new PackedValidationTextureFormat<uint32_t>(11, 11, 10, 0);
+
+ // TODO: Add testing support for BC formats
+// BC1_UNORM,
+// BC1_UNORM_SRGB,
+// BC2_UNORM,
+// BC2_UNORM_SRGB,
+// BC3_UNORM,
+// BC3_UNORM_SRGB,
+// BC4_UNORM,
+// BC4_SNORM,
+// BC5_UNORM,
+// BC5_SNORM,
+// BC6H_UF16,
+// BC6H_SF16,
+// BC7_UNORM,
+// BC7_UNORM_SRGB,
+ default:
+ return nullptr;
+ }
+ }
+
+ struct TextureInfo
+ {
+ ITextureResource::Size extent;
+ int numMipLevels;
+ int arraySize;
+ ITextureResource::SubresourceData const* initData;
+ };
+
+ struct ValidationTextureData : RefObject
+ {
+ const void* textureData;
+ ITextureResource::Size extents;
+ ITextureResource::Offset3D strides;
+
+ void* getBlockAt(Int x, Int y, Int z)
+ {
+ assert(x >= 0 && x < extents.width);
+ assert(y >= 0 && y < extents.height);
+ assert(z >= 0 && z < extents.depth);
+
+ char* layerData = (char*)textureData + z * strides.z;
+ char* rowData = layerData + y * strides.y;
+ return rowData + x * strides.x;
+ }
+ };
+
+ struct TextureToTextureCopyInfo
+ {
+ SubresourceRange srcSubresource;
+ SubresourceRange dstSubresource;
+ ITextureResource::Size extent;
+ ITextureResource::Offset3D srcOffset;
+ ITextureResource::Offset3D dstOffset;
+ };
+
+ struct TextureToBufferCopyInfo
+ {
+ SubresourceRange srcSubresource;
+ ITextureResource::Size extent;
+ ITextureResource::Offset3D textureOffset;
+ size_t bufferOffset;
+ size_t bufferSize;
+ };
+
+ struct TextureStuff : RefObject
+ {
+ List<RefPtr<ValidationTextureData>> subresourceObjects;
+ List<ITextureResource::SubresourceData> subresourceDatas;
+ };
+
struct BaseCopyTextureTest
{
IDevice* device;
UnitTestContext* context;
+ Format format;
+ uint32_t texelSize;
+ size_t alignedRowStride;
+ ITextureResource::Type textureType;
+
+ TextureInfo srcTextureInfo;
+ TextureInfo dstTextureInfo;
+ TextureToTextureCopyInfo texCopyInfo;
+ TextureToBufferCopyInfo bufferCopyInfo;
+
ComPtr<ITextureResource> srcTexture;
ComPtr<ITextureResource> dstTexture;
ComPtr<IBufferResource> resultsBuffer;
- size_t alignedRowPitch;
+ RefPtr<ValidationTextureFormatBase> validationFormat;
+
+ void init(
+ IDevice* device,
+ UnitTestContext* context,
+ Format format,
+ RefPtr<ValidationTextureFormatBase> validationFormat,
+ ITextureResource::Type type)
+ {
+ this->device = device;
+ this->context = context;
+ this->format = format;
+ this->validationFormat = validationFormat;
+ this->textureType = type;
+
+ FormatInfo formatInfo;
+ GFX_CHECK_CALL_ABORT(gfxGetFormatInfo(format, &formatInfo));
+ this->texelSize = formatInfo.blockSizeInBytes / formatInfo.pixelsPerBlock;
+ }
- struct TextureInfo
+ RefPtr<TextureStuff> generateTextureData(int width, int height, int depth, uint32_t mipLevels, uint32_t arrayLayers)
{
- ITextureResource::Size extent;
- int numMipLevels;
- int arraySize;
- ITextureResource::SubresourceData const* initData;
- };
+ RefPtr<TextureStuff> texture = new TextureStuff();
+ for (uint32_t layer = 0; layer < arrayLayers; ++layer)
+ {
+ for (uint32_t mip = 0; mip < mipLevels; ++mip)
+ {
+ RefPtr<ValidationTextureData> subresource = new ValidationTextureData();
- void init(IDevice* device, UnitTestContext* context)
+ auto mipWidth = Math::Max(width >> mip, 1);
+ auto mipHeight = Math::Max(height >> mip, 1);
+ auto mipDepth = Math::Max(depth >> mip, 1);
+ auto mipSize = mipWidth * mipHeight * mipDepth * texelSize;
+ subresource->textureData = malloc(mipSize);
+ SLANG_CHECK_ABORT(subresource->textureData);
+
+ subresource->extents.width = mipWidth;
+ subresource->extents.height = mipHeight;
+ subresource->extents.depth = mipDepth;
+ subresource->strides.x = texelSize;
+ subresource->strides.y = mipWidth * texelSize;
+ subresource->strides.z = mipHeight * subresource->strides.y;
+ texture->subresourceObjects.add(subresource);
+
+ for (int z = 0; z < mipDepth; ++z)
+ {
+ for (int y = 0; y < mipHeight; ++y)
+ {
+ for (int x = 0; x < mipWidth; ++x)
+ {
+ auto texel = subresource->getBlockAt(x, y, z);
+ validationFormat->initializeTexel(texel, x, y, z, mip, layer);
+ }
+ }
+ }
+
+ ITextureResource::SubresourceData subData = {};
+ subData.data = subresource->textureData;
+ subData.strideY = subresource->strides.y;
+ subData.strideZ = subresource->strides.z;
+ texture->subresourceDatas.add(subData);
+ }
+ }
+ return texture;
+ }
+
+ TextureAspect getTextureAspect()
{
- this->device = device;
- this->context = context;
+ switch (format)
+ {
+ case Format::D16_UNORM:
+ case Format::D32_FLOAT:
+ return TextureAspect::Depth;
+ default:
+ return TextureAspect::Color;
+ }
}
- void createRequiredResources(TextureInfo srcTextureInfo, TextureInfo dstTextureInfo, Format format)
+ uint32_t getSubresourceIndex(uint32_t mipLevel, uint32_t mipLevelCount, uint32_t baseArrayLayer)
+ {
+ return baseArrayLayer * mipLevelCount + mipLevel;
+ }
+
+ void createRequiredResources()
{
ITextureResource::Desc srcTexDesc = {};
- srcTexDesc.type = IResource::Type::Texture2D;
+ srcTexDesc.type = textureType;
srcTexDesc.numMipLevels = srcTextureInfo.numMipLevels;
srcTexDesc.arraySize = srcTextureInfo.arraySize;
srcTexDesc.size = srcTextureInfo.extent;
- srcTexDesc.defaultState = ResourceState::UnorderedAccess;
+ srcTexDesc.defaultState = ResourceState::ShaderResource;
srcTexDesc.allowedStates = ResourceStateSet(
- ResourceState::UnorderedAccess,
ResourceState::ShaderResource,
ResourceState::CopySource);
+ if (format == Format::D32_FLOAT || format == Format::D16_UNORM)
+ {
+ srcTexDesc.allowedStates.add(ResourceState::DepthWrite);
+ srcTexDesc.allowedStates.add(ResourceState::DepthRead);
+ }
srcTexDesc.format = format;
GFX_CHECK_CALL_ABORT(device->createTextureResource(
@@ -59,7 +422,7 @@ namespace gfx_test
srcTexture.writeRef()));
ITextureResource::Desc dstTexDesc = {};
- dstTexDesc.type = IResource::Type::Texture2D;
+ dstTexDesc.type = textureType;
dstTexDesc.numMipLevels = dstTextureInfo.numMipLevels;
dstTexDesc.arraySize = dstTextureInfo.arraySize;
dstTexDesc.size = dstTextureInfo.extent;
@@ -68,6 +431,11 @@ namespace gfx_test
ResourceState::ShaderResource,
ResourceState::CopyDestination,
ResourceState::CopySource);
+ if (format == Format::D32_FLOAT || format == Format::D16_UNORM)
+ {
+ srcTexDesc.allowedStates.add(ResourceState::DepthWrite);
+ srcTexDesc.allowedStates.add(ResourceState::DepthRead);
+ }
dstTexDesc.format = format;
GFX_CHECK_CALL_ABORT(device->createTextureResource(
@@ -75,13 +443,12 @@ namespace gfx_test
dstTextureInfo.initData,
dstTexture.writeRef()));
- FormatInfo formatInfo;
- gfxGetFormatInfo(format, &formatInfo);
+ auto bufferCopyExtents = bufferCopyInfo.extent;
size_t alignment;
device->getTextureRowAlignment(&alignment);
- alignedRowPitch = (dstTextureInfo.extent.width * formatInfo.blockSizeInBytes + alignment - 1) & ~(alignment - 1);
+ alignedRowStride = (bufferCopyExtents.width * texelSize + alignment - 1) & ~(alignment - 1);
IBufferResource::Desc bufferDesc = {};
- bufferDesc.sizeInBytes = dstTextureInfo.extent.height * alignedRowPitch;
+ bufferDesc.sizeInBytes = bufferCopyExtents.height * bufferCopyExtents.depth * alignedRowStride;
bufferDesc.format = gfx::Format::Unknown;
bufferDesc.elementSize = 0;
bufferDesc.allowedStates = ResourceStateSet(
@@ -89,6 +456,11 @@ namespace gfx_test
ResourceState::UnorderedAccess,
ResourceState::CopyDestination,
ResourceState::CopySource);
+ if (format == Format::D32_FLOAT || format == Format::D16_UNORM)
+ {
+ srcTexDesc.allowedStates.add(ResourceState::DepthWrite);
+ srcTexDesc.allowedStates.add(ResourceState::DepthRead);
+ }
bufferDesc.defaultState = ResourceState::CopyDestination;
bufferDesc.memoryType = MemoryType::DeviceLocal;
@@ -96,15 +468,11 @@ namespace gfx_test
bufferDesc,
nullptr,
resultsBuffer.writeRef()));
+
+ bufferCopyInfo.bufferSize = bufferDesc.sizeInBytes;
}
- void submitGPUWork(
- SubresourceRange srcSubresource,
- SubresourceRange dstSubresource,
- ITextureResource::Offset3D srcOffset,
- ITextureResource::Offset3D dstOffset,
- ITextureResource::Size extent,
- size_t textureSize)
+ void submitGPUWork()
{
Slang::ComPtr<ITransientResourceHeap> transientHeap;
ITransientResourceHeap::Desc transientHeapDesc = {};
@@ -118,249 +486,664 @@ namespace gfx_test
auto commandBuffer = transientHeap->createCommandBuffer();
auto encoder = commandBuffer->encodeResourceCommands();
- encoder->textureSubresourceBarrier(srcTexture, srcSubresource, ResourceState::UnorderedAccess, ResourceState::CopySource);
- encoder->copyTexture(dstTexture, ResourceState::CopyDestination, dstSubresource, dstOffset, srcTexture, ResourceState::CopySource, srcSubresource, srcOffset, extent);
- encoder->textureSubresourceBarrier(dstTexture, dstSubresource, ResourceState::CopyDestination, ResourceState::CopySource);
- encoder->copyTextureToBuffer(resultsBuffer, 0, textureSize, alignedRowPitch, dstTexture, ResourceState::CopySource, dstSubresource, dstOffset, extent);
+ encoder->textureSubresourceBarrier(srcTexture, texCopyInfo.srcSubresource, ResourceState::ShaderResource, ResourceState::CopySource);
+ encoder->copyTexture(
+ dstTexture,
+ ResourceState::CopyDestination,
+ texCopyInfo.dstSubresource,
+ texCopyInfo.dstOffset,
+ srcTexture,
+ ResourceState::CopySource,
+ texCopyInfo.srcSubresource,
+ texCopyInfo.srcOffset,
+ texCopyInfo.extent);
+
+ encoder->textureSubresourceBarrier(dstTexture, bufferCopyInfo.srcSubresource, ResourceState::CopyDestination, ResourceState::CopySource);
+ encoder->copyTextureToBuffer(
+ resultsBuffer,
+ bufferCopyInfo.bufferOffset,
+ bufferCopyInfo.bufferSize,
+ alignedRowStride,
+ dstTexture,
+ ResourceState::CopySource,
+ bufferCopyInfo.srcSubresource,
+ bufferCopyInfo.textureOffset,
+ bufferCopyInfo.extent);
+
encoder->endEncoding();
commandBuffer->close();
queue->executeCommandBuffer(commandBuffer);
queue->waitOnHost();
}
+
+ bool isWithinCopyBounds(int x, int y, int z)
+ {
+ auto copyExtents = texCopyInfo.extent;
+ auto copyOffset = texCopyInfo.dstOffset;
+
+ auto xLowerBound = copyOffset.x;
+ auto xUpperBound = copyOffset.x + copyExtents.width;
+ auto yLowerBound = copyOffset.y;
+ auto yUpperBound = copyOffset.y + copyExtents.height;
+ auto zLowerBound = copyOffset.z;
+ auto zUpperBound = copyOffset.z + copyExtents.depth;
+
+ if (x < xLowerBound || x >= xUpperBound || y < yLowerBound || y >= yUpperBound || z < zLowerBound || z >= zUpperBound)
+ return false;
+ else
+ return true;
+ }
+
+ void validateTestResults(
+ ValidationTextureData actual,
+ ValidationTextureData expectedCopied,
+ ValidationTextureData expectedOriginal)
+ {
+ auto actualExtents = actual.extents;
+ auto copyExtent = texCopyInfo.extent;
+ auto srcTexOffset = texCopyInfo.srcOffset;
+ auto dstTexOffset = texCopyInfo.dstOffset;
+
+ for (Int x = 0; x < actualExtents.width; ++x)
+ {
+ for (Int y = 0; y < actualExtents.height; ++y)
+ {
+ for (Int z = 0; z < actualExtents.depth; ++z)
+ {
+ auto actualBlock = actual.getBlockAt(x, y, z);
+ if (isWithinCopyBounds(x, y, z))
+ {
+ // Block is located within the bounds of the source texture
+ auto xSource = x + srcTexOffset.x - dstTexOffset.x;
+ auto ySource = y + srcTexOffset.y - dstTexOffset.y;
+ auto zSource = z + srcTexOffset.z - dstTexOffset.z;
+ auto expectedBlock = expectedCopied.getBlockAt(xSource, ySource, zSource);
+ validationFormat->validateBlocksEqual(actualBlock, expectedBlock);
+ }
+ else
+ {
+ // Block is located outside the bounds of the source texture and should be compared
+ // against known expected values for the destination texture.
+ auto expectedBlock = expectedOriginal.getBlockAt(x, y, z);
+ validationFormat->validateBlocksEqual(actualBlock, expectedBlock);
+ }
+ }
+ }
+ }
+ }
+
+ void checkTestResults(ITextureResource::Size srcMipExtent, const void* expectedCopiedData, const void* expectedOriginalData)
+ {
+ ComPtr<ISlangBlob> resultBlob;
+ GFX_CHECK_CALL_ABORT(device->readBufferResource(resultsBuffer, 0, bufferCopyInfo.bufferSize, resultBlob.writeRef()));
+ auto results = resultBlob->getBufferPointer();
+
+ ValidationTextureData actual;
+ actual.extents = bufferCopyInfo.extent;
+ actual.textureData = results;
+ actual.strides.x = texelSize;
+ actual.strides.y = (uint32_t)alignedRowStride;
+ actual.strides.z = actual.extents.height * actual.strides.y;
+
+ ValidationTextureData expectedCopied;
+ expectedCopied.extents = srcMipExtent;
+ expectedCopied.textureData = expectedCopiedData;
+ expectedCopied.strides.x = texelSize;
+ expectedCopied.strides.y = expectedCopied.extents.width * expectedCopied.strides.x;
+ expectedCopied.strides.z = expectedCopied.extents.height * expectedCopied.strides.y;
+
+ ValidationTextureData expectedOriginal;
+ if (expectedOriginalData)
+ {
+ expectedOriginal.extents = bufferCopyInfo.extent;
+ expectedOriginal.textureData = expectedOriginalData;
+ expectedOriginal.strides.x = texelSize;
+ expectedOriginal.strides.y = expectedOriginal.extents.width * expectedOriginal.strides.x;
+ expectedOriginal.strides.z = expectedOriginal.extents.height * expectedOriginal.strides.y;
+ }
+
+ validateTestResults(actual, expectedCopied, expectedOriginal);
+ }
};
struct SimpleCopyTexture : BaseCopyTextureTest
{
- Format format = Format::R8G8B8A8_UINT;
+ void run()
+ {
+ ITextureResource::Size extent = {};
+ extent.width = 4;
+ extent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 4;
+ extent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto mipLevelCount = 1;
+ auto arrayLayerCount = 1;
+
+ auto srcTextureStuff = generateTextureData(extent.width, extent.height, extent.depth, mipLevelCount, arrayLayerCount);
+
+ srcTextureInfo = { extent, mipLevelCount, arrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
+ dstTextureInfo = { extent, mipLevelCount, arrayLayerCount, nullptr };
+
+ SubresourceRange srcSubresource = {};
+ srcSubresource.aspectMask = getTextureAspect();
+ srcSubresource.mipLevel = 0;
+ srcSubresource.mipLevelCount = 1;
+ srcSubresource.baseArrayLayer = 0;
+ srcSubresource.layerCount = 1;
+
+ SubresourceRange dstSubresource = {};
+ dstSubresource.aspectMask = getTextureAspect();
+ dstSubresource.mipLevel = 0;
+ dstSubresource.mipLevelCount = 1;
+ dstSubresource.baseArrayLayer = 0;
+ dstSubresource.layerCount = 1;
+
+ texCopyInfo.srcSubresource = srcSubresource;
+ texCopyInfo.dstSubresource = dstSubresource;
+ texCopyInfo.extent = extent;
+ texCopyInfo.srcOffset = { 0, 0, 0 };
+ texCopyInfo.dstOffset = { 0, 0, 0 };
+
+ bufferCopyInfo.srcSubresource = dstSubresource;
+ bufferCopyInfo.extent = extent;
+ bufferCopyInfo.textureOffset = { 0, 0, 0 };
+ bufferCopyInfo.bufferOffset = 0;
+
+ createRequiredResources();
+ submitGPUWork();
+
+ auto subresourceIndex = getSubresourceIndex(srcSubresource.mipLevel, mipLevelCount, srcSubresource.baseArrayLayer);
+ auto expectedData = srcTextureStuff->subresourceDatas[subresourceIndex];
+ checkTestResults(extent, expectedData.data, nullptr);
+ }
+ };
+ struct CopyTextureSection : BaseCopyTextureTest
+ {
void run()
{
ITextureResource::Size extent = {};
- extent.width = 2;
- extent.height = 2;
- extent.depth = 1;
+ extent.width = 4;
+ extent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 4;
+ extent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto mipLevelCount = 2;
+ auto arrayLayerCount = (textureType == ITextureResource::Type::Texture3D) ? 1 : 2;
+
+ auto srcTextureStuff = generateTextureData(extent.width, extent.height, extent.depth, mipLevelCount, arrayLayerCount);
+
+ srcTextureInfo = { extent, mipLevelCount, arrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
+ dstTextureInfo = { extent, mipLevelCount, arrayLayerCount, nullptr };
+
+ SubresourceRange srcSubresource = {};
+ srcSubresource.aspectMask = getTextureAspect();
+ srcSubresource.mipLevel = 0;
+ srcSubresource.mipLevelCount = 1;
+ srcSubresource.baseArrayLayer = (textureType == ITextureResource::Type::Texture3D) ? 0 : 1;
+ srcSubresource.layerCount = 1;
+
+ SubresourceRange dstSubresource = {};
+ dstSubresource.aspectMask = getTextureAspect();
+ dstSubresource.mipLevel = 0;
+ dstSubresource.mipLevelCount = 1;
+ dstSubresource.baseArrayLayer = 0;
+ dstSubresource.layerCount = 1;
+
+ texCopyInfo.srcSubresource = srcSubresource;
+ texCopyInfo.dstSubresource = dstSubresource;
+ texCopyInfo.extent = extent;
+ texCopyInfo.srcOffset = { 0, 0, 0 };
+ texCopyInfo.dstOffset = { 0, 0, 0 };
+
+ bufferCopyInfo.srcSubresource = dstSubresource;
+ bufferCopyInfo.extent = extent;
+ bufferCopyInfo.textureOffset = { 0, 0, 0 };
+ bufferCopyInfo.bufferOffset = 0;
+
+ createRequiredResources();
+ submitGPUWork();
+
+ auto subresourceIndex = getSubresourceIndex(srcSubresource.mipLevel, mipLevelCount, srcSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedData = srcTextureStuff->subresourceDatas[subresourceIndex];
+ checkTestResults(extent, expectedData.data, nullptr);
+ }
+ };
- uint8_t srcTexData[16] = { 255u, 0u, 0u, 255u, 0u, 255u, 0u, 255u,
- 0u, 0u, 255u, 255u, 127u, 127u, 127u, 255u };
- ITextureResource::SubresourceData srcSubData = { (void*)srcTexData, 8, 0 };
+ struct LargeSrcToSmallDst : BaseCopyTextureTest
+ {
+ void run()
+ {
+ ITextureResource::Size srcExtent = {};
+ srcExtent.width = 8;
+ srcExtent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 8;
+ srcExtent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto srcMipLevelCount = 1;
+ auto srcArrayLayerCount = 1;
- uint8_t dstTexData[16] = { 0u };
- ITextureResource::SubresourceData dstSubData = { (void*)dstTexData, 8, 0 };
+ auto srcTextureStuff = generateTextureData(srcExtent.width, srcExtent.height, srcExtent.depth, srcMipLevelCount, srcArrayLayerCount);
+ srcTextureInfo = { srcExtent, srcMipLevelCount, srcArrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
- TextureInfo srcTextureInfo = { extent, 1, 1, &srcSubData };
- TextureInfo dstTextureInfo = { extent, 1, 1, &dstSubData };
+ ITextureResource::Size dstExtent = {};
+ dstExtent.width = 4;
+ dstExtent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 4;
+ dstExtent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto dstMipLevelCount = 1;
+ auto dstArrayLayerCount = 1;
- createRequiredResources(srcTextureInfo, dstTextureInfo, format);
+ dstTextureInfo = { dstExtent, dstMipLevelCount, dstArrayLayerCount, nullptr };
SubresourceRange srcSubresource = {};
- srcSubresource.aspectMask = TextureAspect::Color;
+ srcSubresource.aspectMask = getTextureAspect();
srcSubresource.mipLevel = 0;
srcSubresource.mipLevelCount = 1;
srcSubresource.baseArrayLayer = 0;
srcSubresource.layerCount = 1;
- ITextureResource::Offset3D srcOffset;
-
SubresourceRange dstSubresource = {};
- dstSubresource.aspectMask = TextureAspect::Color;
+ dstSubresource.aspectMask = getTextureAspect();
dstSubresource.mipLevel = 0;
dstSubresource.mipLevelCount = 1;
dstSubresource.baseArrayLayer = 0;
dstSubresource.layerCount = 1;
- ITextureResource::Offset3D dstOffset;
+ texCopyInfo.srcSubresource = srcSubresource;
+ texCopyInfo.dstSubresource = dstSubresource;
+ texCopyInfo.extent = dstExtent;
+ texCopyInfo.srcOffset = { 0, 0, 0 };
+ texCopyInfo.dstOffset = { 0, 0, 0 };
- submitGPUWork(srcSubresource, dstSubresource, srcOffset, dstOffset, extent, 16);
+ bufferCopyInfo.srcSubresource = dstSubresource;
+ bufferCopyInfo.extent = dstExtent;
+ bufferCopyInfo.textureOffset = { 0, 0, 0 };
+ bufferCopyInfo.bufferOffset = 0;
- if (device->getDeviceInfo().deviceType == DeviceType::DirectX12)
- {
- // D3D12 has to pad out the rows in order to adhere to alignment, so when comparing results
- // we need to make sure not to include the padding.
- size_t testOffset = 0;
- for (Int i = 0; i < extent.height; ++i)
- {
- compareComputeResult(
- device,
- resultsBuffer,
- testOffset,
- srcTexData + 8 * i,
- 8);
- testOffset += alignedRowPitch;
- }
- }
- else if (device->getDeviceInfo().deviceType == DeviceType::Vulkan)
- {
- compareComputeResult(
- device,
- resultsBuffer,
- 0,
- srcTexData,
- 16);
- }
+ createRequiredResources();
+ submitGPUWork();
+
+ auto subresourceIndex = getSubresourceIndex(srcSubresource.mipLevel, srcMipLevelCount, srcSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedData = srcTextureStuff->subresourceDatas[subresourceIndex];
+ checkTestResults(srcExtent, expectedData.data, nullptr);
}
};
- struct Texel
+ struct SmallSrcToLargeDst : BaseCopyTextureTest
{
- float channels[4];
+ void run()
+ {
+ ITextureResource::Size srcExtent = {};
+ srcExtent.width = 4;
+ srcExtent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 4;
+ srcExtent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto srcMipLevelCount = 1;
+ auto srcArrayLayerCount = 1;
+
+ auto srcTextureStuff = generateTextureData(srcExtent.width, srcExtent.height, srcExtent.depth, srcMipLevelCount, srcArrayLayerCount);
+ srcTextureInfo = { srcExtent, srcMipLevelCount, srcArrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
+
+ ITextureResource::Size dstExtent = {};
+ dstExtent.width = 8;
+ dstExtent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 8;
+ dstExtent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto dstMipLevelCount = 1;
+ auto dstArrayLayerCount = 1;
+
+ auto dstTextureStuff = generateTextureData(dstExtent.width, dstExtent.height, dstExtent.depth, dstMipLevelCount, dstArrayLayerCount);
+ dstTextureInfo = { dstExtent, dstMipLevelCount, dstArrayLayerCount, dstTextureStuff->subresourceDatas.getBuffer() };
+
+ SubresourceRange srcSubresource = {};
+ srcSubresource.aspectMask = getTextureAspect();
+ srcSubresource.mipLevel = 0;
+ srcSubresource.mipLevelCount = 1;
+ srcSubresource.baseArrayLayer = 0;
+ srcSubresource.layerCount = 1;
+
+ SubresourceRange dstSubresource = {};
+ dstSubresource.aspectMask = getTextureAspect();
+ dstSubresource.mipLevel = 0;
+ dstSubresource.mipLevelCount = 1;
+ dstSubresource.baseArrayLayer = 0;
+ dstSubresource.layerCount = 1;
+
+ texCopyInfo.srcSubresource = srcSubresource;
+ texCopyInfo.dstSubresource = dstSubresource;
+ texCopyInfo.extent = srcExtent;
+ texCopyInfo.srcOffset = { 0, 0, 0 };
+ texCopyInfo.dstOffset = { 0, 0, 0 };
+
+ bufferCopyInfo.srcSubresource = dstSubresource;
+ bufferCopyInfo.extent = dstExtent;
+ bufferCopyInfo.textureOffset = { 0, 0, 0 };
+ bufferCopyInfo.bufferOffset = 0;
+
+ createRequiredResources();
+ submitGPUWork();
+
+ auto copiedSubresourceIndex = getSubresourceIndex(srcSubresource.mipLevel, srcMipLevelCount, srcSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedCopiedData = srcTextureStuff->subresourceDatas[copiedSubresourceIndex];
+ auto originalSubresourceIndex = getSubresourceIndex(dstSubresource.mipLevel, dstMipLevelCount, dstSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedOriginalData = dstTextureStuff->subresourceDatas[originalSubresourceIndex];
+ checkTestResults(srcExtent, expectedCopiedData.data, expectedOriginalData.data);
+ }
};
- struct SubresourceStuff : RefObject
+ struct CopyBetweenMips : BaseCopyTextureTest
{
- List<Texel> texels;
+ void run()
+ {
+ ITextureResource::Size srcExtent = {};
+ srcExtent.width = 16;
+ srcExtent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 16;
+ srcExtent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto srcMipLevelCount = 4;
+ auto srcArrayLayerCount = 1;
+
+ auto srcTextureStuff = generateTextureData(srcExtent.width, srcExtent.height, srcExtent.depth, srcMipLevelCount, srcArrayLayerCount);
+ srcTextureInfo = { srcExtent, srcMipLevelCount, srcArrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
+
+ ITextureResource::Size dstExtent = {};
+ dstExtent.width = 16;
+ dstExtent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 16;
+ dstExtent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto dstMipLevelCount = 4;
+ auto dstArrayLayerCount = 1;
+
+ auto dstTextureStuff = generateTextureData(dstExtent.width, dstExtent.height, dstExtent.depth, dstMipLevelCount, dstArrayLayerCount);
+ dstTextureInfo = { dstExtent, dstMipLevelCount, dstArrayLayerCount, dstTextureStuff->subresourceDatas.getBuffer() };
+
+ SubresourceRange srcSubresource = {};
+ srcSubresource.aspectMask = getTextureAspect();
+ srcSubresource.mipLevel = 2;
+ srcSubresource.mipLevelCount = 1;
+ srcSubresource.baseArrayLayer = 0;
+ srcSubresource.layerCount = 1;
+
+ SubresourceRange dstSubresource = {};
+ dstSubresource.aspectMask = getTextureAspect();
+ dstSubresource.mipLevel = 1;
+ dstSubresource.mipLevelCount = 1;
+ dstSubresource.baseArrayLayer = 0;
+ dstSubresource.layerCount = 1;
+
+ auto copiedSubresourceIndex = getSubresourceIndex(srcSubresource.mipLevel, srcMipLevelCount, srcSubresource.baseArrayLayer);
+ auto originalSubresourceIndex = getSubresourceIndex(dstSubresource.mipLevel, dstMipLevelCount, dstSubresource.baseArrayLayer);
+
+ texCopyInfo.srcSubresource = srcSubresource;
+ texCopyInfo.dstSubresource = dstSubresource;
+ texCopyInfo.extent = srcTextureStuff->subresourceObjects[copiedSubresourceIndex]->extents;
+ texCopyInfo.srcOffset = { 0, 0, 0 };
+ texCopyInfo.dstOffset = { 0, 0, 0 };
+
+ bufferCopyInfo.srcSubresource = dstSubresource;
+ bufferCopyInfo.extent = dstTextureStuff->subresourceObjects[originalSubresourceIndex]->extents;
+ bufferCopyInfo.textureOffset = { 0, 0, 0 };
+ bufferCopyInfo.bufferOffset = 0;
+
+ createRequiredResources();
+ submitGPUWork();
+
+ ITextureResource::SubresourceData expectedCopiedData = srcTextureStuff->subresourceDatas[copiedSubresourceIndex];
+ ITextureResource::SubresourceData expectedOriginalData = dstTextureStuff->subresourceDatas[originalSubresourceIndex];
+ auto srcMipExtent = srcTextureStuff->subresourceObjects[2]->extents;
+ checkTestResults(srcMipExtent, expectedCopiedData.data, expectedOriginalData.data);
+ }
};
- struct TextureStuff : RefObject
+ struct CopyBetweenLayers : BaseCopyTextureTest
{
- List<RefPtr<SubresourceStuff>> subresourceObjects;
- List<ITextureResource::SubresourceData> subresourceDatas;
+ void run()
+ {
+ ITextureResource::Size extent = {};
+ extent.width = 4;
+ extent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 4;
+ extent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto mipLevelCount = 1;
+ auto arrayLayerCount = (textureType == ITextureResource::Type::Texture3D) ? 1 : 2;
+
+ auto srcTextureStuff = generateTextureData(extent.width, extent.height, extent.depth, mipLevelCount, arrayLayerCount);
+ srcTextureInfo = { extent, mipLevelCount, arrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
+
+ auto dstTextureStuff = generateTextureData(extent.width, extent.height, extent.depth, mipLevelCount, arrayLayerCount);
+ dstTextureInfo = { extent, mipLevelCount, arrayLayerCount, dstTextureStuff->subresourceDatas.getBuffer() };
+
+ SubresourceRange srcSubresource = {};
+ srcSubresource.aspectMask = getTextureAspect();
+ srcSubresource.mipLevel = 0;
+ srcSubresource.mipLevelCount = 1;
+ srcSubresource.baseArrayLayer = 0;
+ srcSubresource.layerCount = 1;
+
+ SubresourceRange dstSubresource = {};
+ dstSubresource.aspectMask = getTextureAspect();
+ dstSubresource.mipLevel = 0;
+ dstSubresource.mipLevelCount = 1;
+ dstSubresource.baseArrayLayer = (textureType == ITextureResource::Type::Texture3D) ? 0 : 1;
+ dstSubresource.layerCount = 1;
+
+ texCopyInfo.srcSubresource = srcSubresource;
+ texCopyInfo.dstSubresource = dstSubresource;
+ texCopyInfo.extent = extent;
+ texCopyInfo.srcOffset = { 0, 0, 0 };
+ texCopyInfo.dstOffset = { 0, 0, 0 };
+
+ bufferCopyInfo.srcSubresource = dstSubresource;
+ bufferCopyInfo.extent = extent;
+ bufferCopyInfo.textureOffset = { 0, 0, 0 };
+ bufferCopyInfo.bufferOffset = 0;
+
+ createRequiredResources();
+ submitGPUWork();
+
+ auto copiedSubresourceIndex = getSubresourceIndex(srcSubresource.mipLevel, mipLevelCount, srcSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedCopiedData = srcTextureStuff->subresourceDatas[copiedSubresourceIndex];
+ auto originalSubresourceIndex = getSubresourceIndex(dstSubresource.mipLevel, mipLevelCount, dstSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedOriginalData = dstTextureStuff->subresourceDatas[originalSubresourceIndex];
+ checkTestResults(extent, expectedCopiedData.data, expectedOriginalData.data);
+ }
};
- struct CopyTextureSection : BaseCopyTextureTest
+ struct CopyWithOffsets : BaseCopyTextureTest
{
- Format format = Format::R32G32B32A32_FLOAT;
-
- RefPtr<TextureStuff> generateTextureData(int width, int height, uint32_t mipLevels, uint32_t arrayLayers)
+ void run()
{
- RefPtr<TextureStuff> texture = new TextureStuff();
- for (uint32_t layer = 0; layer < arrayLayers; ++layer)
- {
- for (uint32_t mip = 0; mip < mipLevels; ++mip)
- {
- RefPtr<SubresourceStuff> subresource = new SubresourceStuff();
- texture->subresourceObjects.add(subresource);
+ ITextureResource::Size srcExtent = {};
+ srcExtent.width = 8;
+ srcExtent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 8;
+ srcExtent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto srcMipLevelCount = 1;
+ auto srcArrayLayerCount = 1;
- int mipWidth = Math::Max(width >> mip, 1);
- int mipHeight = Math::Max(height >> mip, 1);
+ auto srcTextureStuff = generateTextureData(srcExtent.width, srcExtent.height, srcExtent.depth, srcMipLevelCount, srcArrayLayerCount);
+ srcTextureInfo = { srcExtent, srcMipLevelCount, srcArrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
- int mipTexelCount = mipWidth * mipHeight;
- subresource->texels.setCount(mipTexelCount);
- for (int h = 0; h < mipHeight; ++h)
- {
- for (int w = 0; w < mipWidth; ++w)
- {
- // 4 channels per pixel
- subresource->texels[h * mipWidth + w].channels[0] = (float)w;
- subresource->texels[h * mipWidth + w].channels[1] = (float)h;
- subresource->texels[h * mipWidth + w].channels[2] = (float)mip;
- subresource->texels[h * mipWidth + w].channels[3] = (float)layer;
- }
- }
+ ITextureResource::Size dstExtent = {};
+ dstExtent.width = 16;
+ dstExtent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 16;
+ dstExtent.depth = (textureType == ITextureResource::Type::Texture3D) ? 4 : 1;
+ auto dstMipLevelCount = 1;
+ auto dstArrayLayerCount = 1;
- ITextureResource::SubresourceData subData = {};
- subData.data = subresource->texels.getBuffer();
- subData.strideY = mipWidth * sizeof(Texel);
- subData.strideZ = mipHeight * subData.strideY;
- texture->subresourceDatas.add(subData);
- }
+ auto dstTextureStuff = generateTextureData(dstExtent.width, dstExtent.height, dstExtent.depth, dstMipLevelCount, dstArrayLayerCount);
+ dstTextureInfo = { dstExtent, dstMipLevelCount, dstArrayLayerCount, dstTextureStuff->subresourceDatas.getBuffer() };
+
+ SubresourceRange srcSubresource = {};
+ srcSubresource.aspectMask = getTextureAspect();
+ srcSubresource.mipLevel = 0;
+ srcSubresource.mipLevelCount = 1;
+ srcSubresource.baseArrayLayer = 0;
+ srcSubresource.layerCount = 1;
+
+ SubresourceRange dstSubresource = {};
+ dstSubresource.aspectMask = getTextureAspect();
+ dstSubresource.mipLevel = 0;
+ dstSubresource.mipLevelCount = 1;
+ dstSubresource.baseArrayLayer = 0;
+ dstSubresource.layerCount = 1;
+
+ texCopyInfo.srcSubresource = srcSubresource;
+ texCopyInfo.dstSubresource = dstSubresource;
+ texCopyInfo.extent.width = 4;
+ texCopyInfo.extent.height = 4;
+ texCopyInfo.extent.depth = 1;
+ texCopyInfo.srcOffset = { 2, 2, 0 };
+ texCopyInfo.dstOffset = { 4, 4, 0 };
+
+ if (textureType == ITextureResource::Type::Texture1D)
+ {
+ texCopyInfo.extent.height = 1;
+ texCopyInfo.srcOffset.y = 0;
+ texCopyInfo.dstOffset.y = 0;
}
- return texture;
- }
+ else if (textureType == ITextureResource::Type::Texture3D)
+ {
+ texCopyInfo.extent.depth = srcExtent.depth;
+ texCopyInfo.dstOffset.z = 1;
+ }
+
+ bufferCopyInfo.srcSubresource = dstSubresource;
+ bufferCopyInfo.extent = dstExtent;
+ bufferCopyInfo.textureOffset = { 0, 0, 0 };
+ bufferCopyInfo.bufferOffset = 0;
+
+ createRequiredResources();
+ submitGPUWork();
- // TODO: Things to test in the future
- // 1. Size of src texture(W, H, mips, layers)
- // 2. Size of dst texture(...)
- // 3. src subresource(mip, layer)
- // 4. dst subresource(mip, layer)
- // 5. copy extents(x, y)
- // 6. copy src coords(x, y)
- // 7. copy dst coords(x, y)
- // 8. Final buffer offset
+ auto copiedSubresourceIndex = getSubresourceIndex(srcSubresource.mipLevel, srcMipLevelCount, srcSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedCopiedData = srcTextureStuff->subresourceDatas[copiedSubresourceIndex];
+ auto originalSubresourceIndex = getSubresourceIndex(dstSubresource.mipLevel, dstMipLevelCount, dstSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedOriginalData = dstTextureStuff->subresourceDatas[originalSubresourceIndex];
+ checkTestResults(srcExtent, expectedCopiedData.data, expectedOriginalData.data);
+ }
+ };
+ struct CopySectionWithSetExtent : BaseCopyTextureTest
+ {
void run()
{
ITextureResource::Size extent = {};
- extent.width = 4;
- extent.height = 4;
- extent.depth = 1;
-
- auto mipLevelCount = 2;
- auto arrayLayerCount = 2;
+ extent.width = 8;
+ extent.height = (textureType == ITextureResource::Type::Texture1D) ? 1 : 8;
+ extent.depth = (textureType == ITextureResource::Type::Texture3D) ? 2 : 1;
+ auto mipLevelCount = 1;
+ auto arrayLayerCount = 1;
- auto srcTextureStuff = generateTextureData(extent.width, extent.height, mipLevelCount, arrayLayerCount);
-
- TextureInfo srcTextureInfo = { extent, mipLevelCount, arrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
- TextureInfo dstTextureInfo = { extent, mipLevelCount, arrayLayerCount, nullptr };
+ auto srcTextureStuff = generateTextureData(extent.width, extent.height, extent.depth, mipLevelCount, arrayLayerCount);
+ srcTextureInfo = { extent, mipLevelCount, arrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
- createRequiredResources(srcTextureInfo, dstTextureInfo, format);
+ auto dstTextureStuff = generateTextureData(extent.width, extent.height, extent.depth, mipLevelCount, arrayLayerCount);
+ dstTextureInfo = { extent, mipLevelCount, arrayLayerCount, dstTextureStuff->subresourceDatas.getBuffer() };
SubresourceRange srcSubresource = {};
- srcSubresource.aspectMask = TextureAspect::Color;
+ srcSubresource.aspectMask = getTextureAspect();
srcSubresource.mipLevel = 0;
srcSubresource.mipLevelCount = 1;
- srcSubresource.baseArrayLayer = 1;
+ srcSubresource.baseArrayLayer = 0;
srcSubresource.layerCount = 1;
- ITextureResource::Offset3D srcOffset;
-
SubresourceRange dstSubresource = {};
- dstSubresource.aspectMask = TextureAspect::Color;
+ dstSubresource.aspectMask = getTextureAspect();
dstSubresource.mipLevel = 0;
dstSubresource.mipLevelCount = 1;
dstSubresource.baseArrayLayer = 0;
dstSubresource.layerCount = 1;
- ITextureResource::Offset3D dstOffset;
+ texCopyInfo.srcSubresource = srcSubresource;
+ texCopyInfo.dstSubresource = dstSubresource;
+ texCopyInfo.extent.width = 4;
+ texCopyInfo.extent.height = 4;
+ texCopyInfo.extent.depth = 1;
+ texCopyInfo.srcOffset = { 0, 0, 0 };
+ texCopyInfo.dstOffset = { 4, 4, 0 };
- submitGPUWork(srcSubresource, dstSubresource, srcOffset, dstOffset, extent, extent.height * 256);
-
- ITextureResource::SubresourceData expectedData = srcTextureStuff->subresourceDatas[2];
- if (device->getDeviceInfo().deviceType == DeviceType::DirectX12)
+ if (textureType == ITextureResource::Type::Texture1D)
{
- // D3D12 has to pad out the rows in order to adhere to alignment, so when comparing results
- // we need to make sure not to include the padding.
- size_t testOffset = 0;
- size_t dataOffset = 0;
- auto rowStride = expectedData.strideY / 4;
- for (Int i = 0; i < extent.height; ++i)
- {
- compareComputeResult(
- device,
- resultsBuffer,
- testOffset,
- (float*) expectedData.data + rowStride * i,
- rowStride * 4);
- testOffset += alignedRowPitch;
- }
- dataOffset += srcTextureStuff->subresourceDatas[0].strideZ / 4;
+ texCopyInfo.extent.height = 1;
+ texCopyInfo.dstOffset.y = 0;
}
- else if (device->getDeviceInfo().deviceType == DeviceType::Vulkan)
+ else if (textureType == ITextureResource::Type::Texture3D)
{
- compareComputeResult(
- device,
- resultsBuffer,
- 0,
- expectedData.data,
- 64);
+ texCopyInfo.extent.depth = extent.depth;
}
+
+ bufferCopyInfo.srcSubresource = dstSubresource;
+ bufferCopyInfo.extent = extent;
+ bufferCopyInfo.textureOffset = { 0, 0, 0 };
+ bufferCopyInfo.bufferOffset = 0;
+
+ createRequiredResources();
+ submitGPUWork();
+
+ auto copiedSubresourceIndex = getSubresourceIndex(srcSubresource.mipLevel, mipLevelCount, srcSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedCopiedData = srcTextureStuff->subresourceDatas[copiedSubresourceIndex];
+ auto originalSubresourceIndex = getSubresourceIndex(dstSubresource.mipLevel, mipLevelCount, dstSubresource.baseArrayLayer);
+ ITextureResource::SubresourceData expectedOriginalData = dstTextureStuff->subresourceDatas[originalSubresourceIndex];
+ checkTestResults(extent, expectedCopiedData.data, expectedOriginalData.data);
}
};
template<typename T>
void copyTextureTestImpl(IDevice* device, UnitTestContext* context)
{
- T test;
- test.init(device, context);
- test.run();
+ // Skip Type::Unknown and Type::Buffer as well as Format::Unknown
+ // TODO: Add support for TextureCube
+ for (uint32_t i = 2; i < (uint32_t)ITextureResource::Type::CountOf - 1; ++i)
+ {
+ for (uint32_t j = 1; j < (uint32_t)Format::CountOf; ++j)
+ {
+ auto type = (ITextureResource::Type)i;
+ auto format = (Format)j;
+ auto validationFormat = getValidationTextureFormat(format);
+ if (!validationFormat)
+ continue;
+
+ T test;
+ test.init(device, context, format, validationFormat, type);
+ test.run();
+ }
+ }
}
- SLANG_UNIT_TEST(copyTextureSimpleD3D12)
+ SLANG_UNIT_TEST(copyTextureSimple)
{
runTestImpl(copyTextureTestImpl<SimpleCopyTexture>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ runTestImpl(copyTextureTestImpl<SimpleCopyTexture>, unitTestContext, Slang::RenderApiFlag::Vulkan);
}
- SLANG_UNIT_TEST(copyTextureSectionD3D12)
+ SLANG_UNIT_TEST(copyTextureSection)
{
runTestImpl(copyTextureTestImpl<CopyTextureSection>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ runTestImpl(copyTextureTestImpl<CopyTextureSection>, unitTestContext, Slang::RenderApiFlag::Vulkan);
}
- SLANG_UNIT_TEST(copyTextureSimpleVulkan)
+ SLANG_UNIT_TEST(copyLargeToSmallTexture)
{
- runTestImpl(copyTextureTestImpl<SimpleCopyTexture>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ runTestImpl(copyTextureTestImpl<LargeSrcToSmallDst>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ runTestImpl(copyTextureTestImpl<LargeSrcToSmallDst>, unitTestContext, Slang::RenderApiFlag::Vulkan);
}
- SLANG_UNIT_TEST(copyTextureSectionVulkan)
+ SLANG_UNIT_TEST(copySmallToLargeTexture)
{
- runTestImpl(copyTextureTestImpl<CopyTextureSection>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ runTestImpl(copyTextureTestImpl<SmallSrcToLargeDst>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ runTestImpl(copyTextureTestImpl<SmallSrcToLargeDst>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
+
+ SLANG_UNIT_TEST(copyBetweenMips)
+ {
+ runTestImpl(copyTextureTestImpl<CopyBetweenMips>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ runTestImpl(copyTextureTestImpl<CopyBetweenMips>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
+
+ SLANG_UNIT_TEST(copyBetweenLayers)
+ {
+ runTestImpl(copyTextureTestImpl<CopyBetweenLayers>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ runTestImpl(copyTextureTestImpl<CopyBetweenLayers>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
+
+ SLANG_UNIT_TEST(copyWithOffsets)
+ {
+ runTestImpl(copyTextureTestImpl<CopyWithOffsets>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ runTestImpl(copyTextureTestImpl<CopyWithOffsets>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
+
+ SLANG_UNIT_TEST(copySectionWithSetExtent)
+ {
+ runTestImpl(copyTextureTestImpl<CopySectionWithSetExtent>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ runTestImpl(copyTextureTestImpl<CopySectionWithSetExtent>, unitTestContext, Slang::RenderApiFlag::Vulkan);
}
}