| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2015-2020 The Khronos Group Inc. |
| * Copyright (c) 2020 Google Inc. |
| * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Vulkan Copies And Blitting Tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktApiCopiesAndBlittingTests.hpp" |
| |
| #include "deStringUtil.hpp" |
| #include "deUniquePtr.hpp" |
| |
| #include "tcuImageCompare.hpp" |
| #include "tcuAstcUtil.hpp" |
| #include "tcuTexture.hpp" |
| #include "tcuTextureUtil.hpp" |
| #include "tcuVectorType.hpp" |
| #include "tcuVectorUtil.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuTexLookupVerifier.hpp" |
| |
| #include "vkImageUtil.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkPrograms.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vktTestCase.hpp" |
| #include "vktTestCaseUtil.hpp" |
| #include "vktTestGroupUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkObjUtil.hpp" |
| #include "vkBuilderUtil.hpp" |
| #include "vkBufferWithMemory.hpp" |
| #include "vkBarrierUtil.hpp" |
| |
| #include "pipeline/vktPipelineImageUtil.hpp" // required for compressed image blit |
| |
| #include <set> |
| #include <array> |
| #include <algorithm> |
| #include <iterator> |
| #include <sstream> |
| |
| namespace vkt |
| { |
| |
| namespace api |
| { |
| |
| namespace |
| { |
| |
| enum FillMode |
| { |
| FILL_MODE_GRADIENT = 0, |
| FILL_MODE_WHITE, |
| FILL_MODE_BLACK, |
| FILL_MODE_RED, |
| FILL_MODE_MULTISAMPLE, |
| FILL_MODE_BLUE_RED_X, |
| FILL_MODE_BLUE_RED_Y, |
| FILL_MODE_BLUE_RED_Z, |
| |
| FILL_MODE_LAST |
| }; |
| |
| enum MirrorModeBits |
| { |
| MIRROR_MODE_X = (1<<0), |
| MIRROR_MODE_Y = (1<<1), |
| MIRROR_MODE_Z = (1<<2), |
| MIRROR_MODE_LAST = (1<<3), |
| }; |
| |
| using MirrorMode = deUint32; |
| |
| enum AllocationKind |
| { |
| ALLOCATION_KIND_SUBALLOCATED, |
| ALLOCATION_KIND_DEDICATED, |
| }; |
| |
| enum ExtensionUse |
| { |
| EXTENSION_USE_NONE, |
| EXTENSION_USE_COPY_COMMANDS2, |
| }; |
| |
| template <typename Type> |
| class BinaryCompare |
| { |
| public: |
| bool operator() (const Type& a, const Type& b) const |
| { |
| return deMemCmp(&a, &b, sizeof(Type)) < 0; |
| } |
| }; |
| |
| typedef std::set<vk::VkFormat, BinaryCompare<vk::VkFormat> > FormatSet; |
| |
| FormatSet dedicatedAllocationImageToImageFormatsToTestSet; |
| FormatSet dedicatedAllocationBlittingFormatsToTestSet; |
| |
| using namespace vk; |
| |
| VkImageCopy2KHR convertvkImageCopyTovkImageCopy2KHR(VkImageCopy imageCopy) |
| { |
| const VkImageCopy2KHR imageCopy2 = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| imageCopy.srcSubresource, // VkImageSubresourceLayers srcSubresource; |
| imageCopy.srcOffset, // VkOffset3D srcOffset; |
| imageCopy.dstSubresource, // VkImageSubresourceLayers dstSubresource; |
| imageCopy.dstOffset, // VkOffset3D dstOffset; |
| imageCopy.extent // VkExtent3D extent; |
| }; |
| return imageCopy2; |
| } |
| VkBufferCopy2KHR convertvkBufferCopyTovkBufferCopy2KHR(VkBufferCopy bufferCopy) |
| { |
| const VkBufferCopy2KHR bufferCopy2 = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| bufferCopy.srcOffset, // VkDeviceSize srcOffset; |
| bufferCopy.dstOffset, // VkDeviceSize dstOffset; |
| bufferCopy.size, // VkDeviceSize size; |
| }; |
| return bufferCopy2; |
| } |
| |
| VkBufferImageCopy2KHR convertvkBufferImageCopyTovkBufferImageCopy2KHR(VkBufferImageCopy bufferImageCopy) |
| { |
| const VkBufferImageCopy2KHR bufferImageCopy2 = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| bufferImageCopy.bufferOffset, // VkDeviceSize bufferOffset; |
| bufferImageCopy.bufferRowLength, // uint32_t bufferRowLength; |
| bufferImageCopy.bufferImageHeight, // uint32_t bufferImageHeight; |
| bufferImageCopy.imageSubresource, // VkImageSubresourceLayers imageSubresource; |
| bufferImageCopy.imageOffset, // VkOffset3D imageOffset; |
| bufferImageCopy.imageExtent // VkExtent3D imageExtent; |
| }; |
| return bufferImageCopy2; |
| } |
| |
| VkImageBlit2KHR convertvkImageBlitTovkImageBlit2KHR(VkImageBlit imageBlit) |
| { |
| const VkImageBlit2KHR imageBlit2 = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| imageBlit.srcSubresource, // VkImageSubresourceLayers srcSubresource; |
| { // VkOffset3D srcOffsets[2]; |
| { |
| imageBlit.srcOffsets[0].x, // VkOffset3D srcOffsets[0].x; |
| imageBlit.srcOffsets[0].y, // VkOffset3D srcOffsets[0].y; |
| imageBlit.srcOffsets[0].z // VkOffset3D srcOffsets[0].z; |
| }, |
| { |
| imageBlit.srcOffsets[1].x, // VkOffset3D srcOffsets[1].x; |
| imageBlit.srcOffsets[1].y, // VkOffset3D srcOffsets[1].y; |
| imageBlit.srcOffsets[1].z // VkOffset3D srcOffsets[1].z; |
| } |
| }, |
| imageBlit.dstSubresource, // VkImageSubresourceLayers dstSubresource; |
| { // VkOffset3D srcOffsets[2]; |
| { |
| imageBlit.dstOffsets[0].x, // VkOffset3D dstOffsets[0].x; |
| imageBlit.dstOffsets[0].y, // VkOffset3D dstOffsets[0].y; |
| imageBlit.dstOffsets[0].z // VkOffset3D dstOffsets[0].z; |
| }, |
| { |
| imageBlit.dstOffsets[1].x, // VkOffset3D dstOffsets[1].x; |
| imageBlit.dstOffsets[1].y, // VkOffset3D dstOffsets[1].y; |
| imageBlit.dstOffsets[1].z // VkOffset3D dstOffsets[1].z; |
| } |
| } |
| }; |
| return imageBlit2; |
| } |
| |
| VkImageResolve2KHR convertvkImageResolveTovkImageResolve2KHR(VkImageResolve imageResolve) |
| { |
| const VkImageResolve2KHR imageResolve2 = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| imageResolve.srcSubresource, // VkImageSubresourceLayers srcSubresource; |
| imageResolve.srcOffset, // VkOffset3D srcOffset; |
| imageResolve.dstSubresource, // VkImageSubresourceLayers dstSubresource; |
| imageResolve.dstOffset, // VkOffset3D dstOffset; |
| imageResolve.extent // VkExtent3D extent; |
| }; |
| return imageResolve2; |
| } |
| |
| VkImageAspectFlags getAspectFlags (tcu::TextureFormat format) |
| { |
| VkImageAspectFlags aspectFlag = 0; |
| aspectFlag |= (tcu::hasDepthComponent(format.order)? VK_IMAGE_ASPECT_DEPTH_BIT : 0); |
| aspectFlag |= (tcu::hasStencilComponent(format.order)? VK_IMAGE_ASPECT_STENCIL_BIT : 0); |
| |
| if (!aspectFlag) |
| aspectFlag = VK_IMAGE_ASPECT_COLOR_BIT; |
| |
| return aspectFlag; |
| } |
| |
| VkImageAspectFlags getAspectFlags (VkFormat format) |
| { |
| if (isCompressedFormat(format)) |
| return VK_IMAGE_ASPECT_COLOR_BIT; |
| else |
| return getAspectFlags(mapVkFormat(format)); |
| } |
| |
| tcu::TextureFormat getSizeCompatibleTcuTextureFormat (VkFormat format) |
| { |
| if (isCompressedFormat(format)) |
| return (getBlockSizeInBytes(format) == 8) ? mapVkFormat(VK_FORMAT_R16G16B16A16_UINT) : mapVkFormat(VK_FORMAT_R32G32B32A32_UINT); |
| else |
| return mapVkFormat(format); |
| } |
| |
| // This is effectively same as vk::isFloatFormat(mapTextureFormat(format)) |
| // except that it supports some formats that are not mappable to VkFormat. |
| // When we are checking combined depth and stencil formats, each aspect is |
| // checked separately, and in some cases we construct PBA with a format that |
| // is not mappable to VkFormat. |
| bool isFloatFormat (tcu::TextureFormat format) |
| { |
| return tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT; |
| } |
| |
| union CopyRegion |
| { |
| VkBufferCopy bufferCopy; |
| VkImageCopy imageCopy; |
| VkBufferImageCopy bufferImageCopy; |
| VkImageBlit imageBlit; |
| VkImageResolve imageResolve; |
| }; |
| |
| struct ImageParms |
| { |
| VkImageType imageType; |
| VkFormat format; |
| VkExtent3D extent; |
| VkImageTiling tiling; |
| VkImageLayout operationLayout; |
| VkImageCreateFlags createFlags; |
| FillMode fillMode; |
| }; |
| |
| struct TestParams |
| { |
| union Data |
| { |
| struct Buffer |
| { |
| VkDeviceSize size; |
| } buffer; |
| |
| ImageParms image; |
| } src, dst; |
| |
| std::vector<CopyRegion> regions; |
| |
| union |
| { |
| VkFilter filter; |
| VkSampleCountFlagBits samples; |
| }; |
| |
| AllocationKind allocationKind; |
| ExtensionUse extensionUse; |
| deUint32 mipLevels; |
| deBool singleCommand; |
| deUint32 barrierCount; |
| deBool separateDepthStencilLayouts; |
| deBool clearDestination; |
| |
| TestParams (void) |
| { |
| allocationKind = ALLOCATION_KIND_DEDICATED; |
| extensionUse = EXTENSION_USE_NONE; |
| mipLevels = 1u; |
| singleCommand = DE_TRUE; |
| barrierCount = 1u; |
| separateDepthStencilLayouts = DE_FALSE; |
| src.image.createFlags = VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM; |
| dst.image.createFlags = VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM; |
| src.image.fillMode = FILL_MODE_GRADIENT; |
| dst.image.fillMode = FILL_MODE_WHITE; |
| clearDestination = DE_FALSE; |
| samples = VK_SAMPLE_COUNT_1_BIT; |
| } |
| }; |
| |
| de::MovePtr<Allocation> allocateBuffer (const InstanceInterface& vki, |
| const DeviceInterface& vkd, |
| const VkPhysicalDevice& physDevice, |
| const VkDevice device, |
| const VkBuffer& buffer, |
| const MemoryRequirement requirement, |
| Allocator& allocator, |
| AllocationKind allocationKind) |
| { |
| switch (allocationKind) |
| { |
| case ALLOCATION_KIND_SUBALLOCATED: |
| { |
| const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer); |
| |
| return allocator.allocate(memoryRequirements, requirement); |
| } |
| |
| case ALLOCATION_KIND_DEDICATED: |
| { |
| return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement); |
| } |
| |
| default: |
| { |
| TCU_THROW(InternalError, "Invalid allocation kind"); |
| } |
| } |
| } |
| |
| de::MovePtr<Allocation> allocateImage (const InstanceInterface& vki, |
| const DeviceInterface& vkd, |
| const VkPhysicalDevice& physDevice, |
| const VkDevice device, |
| const VkImage& image, |
| const MemoryRequirement requirement, |
| Allocator& allocator, |
| AllocationKind allocationKind) |
| { |
| switch (allocationKind) |
| { |
| case ALLOCATION_KIND_SUBALLOCATED: |
| { |
| const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image); |
| |
| return allocator.allocate(memoryRequirements, requirement); |
| } |
| |
| case ALLOCATION_KIND_DEDICATED: |
| { |
| return allocateDedicated(vki, vkd, physDevice, device, image, requirement); |
| } |
| |
| default: |
| { |
| TCU_THROW(InternalError, "Invalid allocation kind"); |
| } |
| } |
| } |
| |
| |
| inline deUint32 getArraySize(const ImageParms& parms) |
| { |
| return (parms.imageType != VK_IMAGE_TYPE_3D) ? parms.extent.depth : 1u; |
| } |
| |
| inline VkImageCreateFlags getCreateFlags(const ImageParms& parms) |
| { |
| if (parms.createFlags == VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM) |
| return parms.imageType == VK_IMAGE_TYPE_2D && parms.extent.depth % 6 == 0 ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0; |
| else |
| return parms.createFlags; |
| } |
| |
| inline VkExtent3D getExtent3D(const ImageParms& parms, deUint32 mipLevel = 0u) |
| { |
| const bool isCompressed = isCompressedFormat(parms.format); |
| const deUint32 blockWidth = (isCompressed) ? getBlockWidth(parms.format) : 1u; |
| const deUint32 blockHeight = (isCompressed) ? getBlockHeight(parms.format) : 1u; |
| |
| if (isCompressed && mipLevel != 0u) |
| DE_FATAL("Not implemented"); |
| |
| const VkExtent3D extent = |
| { |
| (parms.extent.width >> mipLevel) * blockWidth, |
| (parms.imageType != VK_IMAGE_TYPE_1D) ? ((parms.extent.height >> mipLevel) * blockHeight) : 1u, |
| (parms.imageType == VK_IMAGE_TYPE_3D) ? parms.extent.depth : 1u, |
| }; |
| return extent; |
| } |
| |
| const tcu::TextureFormat mapCombinedToDepthTransferFormat (const tcu::TextureFormat& combinedFormat) |
| { |
| tcu::TextureFormat format; |
| switch (combinedFormat.type) |
| { |
| case tcu::TextureFormat::UNORM_INT16: |
| case tcu::TextureFormat::UNSIGNED_INT_16_8_8: |
| format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16); |
| break; |
| case tcu::TextureFormat::UNSIGNED_INT_24_8_REV: |
| format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8_REV); |
| break; |
| case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: |
| case tcu::TextureFormat::FLOAT: |
| format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT); |
| break; |
| default: |
| DE_ASSERT(false); |
| break; |
| } |
| return format; |
| } |
| |
| class CopiesAndBlittingTestInstance : public vkt::TestInstance |
| { |
| public: |
| CopiesAndBlittingTestInstance (Context& context, |
| TestParams testParams); |
| virtual tcu::TestStatus iterate (void) = 0; |
| |
| protected: |
| const TestParams m_params; |
| |
| Move<VkCommandPool> m_cmdPool; |
| Move<VkCommandBuffer> m_cmdBuffer; |
| Move<VkFence> m_fence; |
| de::MovePtr<tcu::TextureLevel> m_sourceTextureLevel; |
| de::MovePtr<tcu::TextureLevel> m_destinationTextureLevel; |
| de::MovePtr<tcu::TextureLevel> m_expectedTextureLevel[16]; |
| |
| VkCommandBufferBeginInfo m_cmdBufferBeginInfo; |
| |
| void generateBuffer (tcu::PixelBufferAccess buffer, int width, int height, int depth = 1, FillMode = FILL_MODE_GRADIENT); |
| virtual void generateExpectedResult (void); |
| void uploadBuffer (tcu::ConstPixelBufferAccess bufferAccess, const Allocation& bufferAlloc); |
| void uploadImage (const tcu::ConstPixelBufferAccess& src, VkImage dst, const ImageParms& parms, const deUint32 mipLevels = 1u); |
| virtual tcu::TestStatus checkTestResult (tcu::ConstPixelBufferAccess result); |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel = 0u) = 0; |
| deUint32 calculateSize (tcu::ConstPixelBufferAccess src) const |
| { |
| return src.getWidth() * src.getHeight() * src.getDepth() * tcu::getPixelSize(src.getFormat()); |
| } |
| |
| de::MovePtr<tcu::TextureLevel> readImage (vk::VkImage image, |
| const ImageParms& imageParms, |
| const deUint32 mipLevel = 0u); |
| |
| private: |
| void uploadImageAspect (const tcu::ConstPixelBufferAccess& src, |
| const VkImage& dst, |
| const ImageParms& parms, |
| const deUint32 mipLevels = 1u); |
| void readImageAspect (vk::VkImage src, |
| const tcu::PixelBufferAccess& dst, |
| const ImageParms& parms, |
| const deUint32 mipLevel = 0u); |
| }; |
| |
| CopiesAndBlittingTestInstance::CopiesAndBlittingTestInstance (Context& context, TestParams testParams) |
| : vkt::TestInstance (context) |
| , m_params (testParams) |
| { |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| |
| // Create command pool |
| m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex); |
| |
| // Create command buffer |
| m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| |
| // Create fence |
| m_fence = createFence(vk, vkDevice); |
| } |
| |
| void CopiesAndBlittingTestInstance::generateBuffer (tcu::PixelBufferAccess buffer, int width, int height, int depth, FillMode mode) |
| { |
| const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(buffer.getFormat().type); |
| tcu::Vec4 maxValue (1.0f); |
| |
| if (buffer.getFormat().order == tcu::TextureFormat::S) |
| { |
| // Stencil-only is stored in the first component. Stencil is always 8 bits. |
| maxValue.x() = 1 << 8; |
| } |
| else if (buffer.getFormat().order == tcu::TextureFormat::DS) |
| { |
| // In a combined format, fillWithComponentGradients expects stencil in the fourth component. |
| maxValue.w() = 1 << 8; |
| } |
| else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) |
| { |
| // The tcu::Vectors we use as pixels are 32-bit, so clamp to that. |
| const tcu::IVec4 bits = tcu::min(tcu::getTextureFormatBitDepth(buffer.getFormat()), tcu::IVec4(32)); |
| const int signBit = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? 1 : 0); |
| |
| for (int i = 0; i < 4; ++i) |
| { |
| if (bits[i] != 0) |
| maxValue[i] = static_cast<float>((deUint64(1) << (bits[i] - signBit)) - 1); |
| } |
| } |
| |
| if (mode == FILL_MODE_GRADIENT) |
| { |
| tcu::fillWithComponentGradients2(buffer, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), maxValue); |
| return; |
| } |
| |
| const tcu::Vec4 redColor (maxValue.x(), 0.0, 0.0, maxValue.w()); |
| const tcu::Vec4 greenColor (0.0, maxValue.y(), 0.0, maxValue.w()); |
| const tcu::Vec4 blueColor (0.0, 0.0, maxValue.z(), maxValue.w()); |
| const tcu::Vec4 whiteColor (maxValue.x(), maxValue.y(), maxValue.z(), maxValue.w()); |
| const tcu::Vec4 blackColor (0.0f, 0.0f, 0.0f, 0.0f); |
| |
| for (int z = 0; z < depth; ++z) |
| for (int y = 0; y < height; ++y) |
| for (int x = 0; x < width; ++x) |
| { |
| switch (mode) |
| { |
| case FILL_MODE_WHITE: |
| if (tcu::isCombinedDepthStencilType(buffer.getFormat().type)) |
| { |
| buffer.setPixDepth(1.0f, x, y, z); |
| if (tcu::hasStencilComponent(buffer.getFormat().order)) |
| buffer.setPixStencil(255, x, y, z); |
| } |
| else |
| buffer.setPixel(whiteColor, x, y, z); |
| break; |
| |
| case FILL_MODE_BLACK: |
| if (tcu::isCombinedDepthStencilType(buffer.getFormat().type)) |
| { |
| buffer.setPixDepth(0.0f, x, y, z); |
| if (tcu::hasStencilComponent(buffer.getFormat().order)) |
| buffer.setPixStencil(0, x, y, z); |
| } |
| else |
| buffer.setPixel(blackColor, x, y, z); |
| break; |
| |
| case FILL_MODE_RED: |
| if (tcu::isCombinedDepthStencilType(buffer.getFormat().type)) |
| { |
| buffer.setPixDepth(redColor[0], x, y, z); |
| if (tcu::hasStencilComponent(buffer.getFormat().order)) |
| buffer.setPixStencil((int)redColor[3], x, y, z); |
| } |
| else |
| buffer.setPixel(redColor, x, y, z); |
| break; |
| |
| case FILL_MODE_BLUE_RED_X: |
| case FILL_MODE_BLUE_RED_Y: |
| case FILL_MODE_BLUE_RED_Z: |
| bool useBlue; |
| switch (mode) |
| { |
| case FILL_MODE_BLUE_RED_X: useBlue = (x & 1); break; |
| case FILL_MODE_BLUE_RED_Y: useBlue = (y & 1); break; |
| case FILL_MODE_BLUE_RED_Z: useBlue = (z & 1); break; |
| default: DE_ASSERT(false); break; |
| } |
| if (tcu::isCombinedDepthStencilType(buffer.getFormat().type)) |
| { |
| buffer.setPixDepth((useBlue ? blueColor[0] : redColor[0]), x, y, z); |
| if (tcu::hasStencilComponent(buffer.getFormat().order)) |
| buffer.setPixStencil((useBlue ? (int) blueColor[3] : (int)redColor[3]), x, y, z); |
| } |
| else |
| buffer.setPixel((useBlue ? blueColor : redColor), x, y, z); |
| break; |
| |
| case FILL_MODE_MULTISAMPLE: |
| { |
| float xScaled = static_cast<float>(x) / static_cast<float>(width); |
| float yScaled = static_cast<float>(y) / static_cast<float>(height); |
| buffer.setPixel((xScaled == yScaled) ? tcu::Vec4(0.0, 0.5, 0.5, 1.0) : ((xScaled > yScaled) ? greenColor : blueColor), x, y, z); |
| break; |
| } |
| |
| default: |
| break; |
| } |
| } |
| } |
| |
| void CopiesAndBlittingTestInstance::uploadBuffer (tcu::ConstPixelBufferAccess bufferAccess, const Allocation& bufferAlloc) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const deUint32 bufferSize = calculateSize(bufferAccess); |
| |
| // Write buffer data |
| deMemcpy(bufferAlloc.getHostPtr(), bufferAccess.getDataPtr(), bufferSize); |
| flushAlloc(vk, vkDevice, bufferAlloc); |
| } |
| |
| void CopiesAndBlittingTestInstance::uploadImageAspect (const tcu::ConstPixelBufferAccess& imageAccess, const VkImage& image, const ImageParms& parms, const deUint32 mipLevels) |
| { |
| const InstanceInterface& vki = m_context.getInstanceInterface(); |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = m_context.getPhysicalDevice(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = m_context.getDefaultAllocator(); |
| Move<VkBuffer> buffer; |
| const deUint32 bufferSize = calculateSize(imageAccess); |
| de::MovePtr<Allocation> bufferAlloc; |
| const deUint32 arraySize = getArraySize(parms); |
| const VkExtent3D imageExtent = getExtent3D(parms); |
| std::vector <VkBufferImageCopy> copyRegions; |
| |
| // Create source buffer |
| { |
| const VkBufferCreateInfo bufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| bufferSize, // VkDeviceSize size; |
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| buffer = createBuffer(vk, vkDevice, &bufferParams); |
| bufferAlloc = allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *buffer, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset())); |
| } |
| |
| // Barriers for copying buffer to image |
| const VkBufferMemoryBarrier preBufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *buffer, // VkBuffer buffer; |
| 0u, // VkDeviceSize offset; |
| bufferSize // VkDeviceSize size; |
| }; |
| |
| const VkImageAspectFlags formatAspect = (m_params.separateDepthStencilLayouts) ? getAspectFlags(imageAccess.getFormat()) : getAspectFlags(parms.format); |
| const bool skipPreImageBarrier = (m_params.separateDepthStencilLayouts) ? false : ((formatAspect == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) && |
| getAspectFlags(imageAccess.getFormat()) == VK_IMAGE_ASPECT_STENCIL_BIT)); |
| |
| const VkImageMemoryBarrier preImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| image, // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| formatAspect, // VkImageAspectFlags aspect; |
| 0u, // deUint32 baseMipLevel; |
| mipLevels, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| arraySize, // deUint32 arraySize; |
| } |
| }; |
| |
| const VkImageMemoryBarrier postImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| image, // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| formatAspect, // VkImageAspectFlags aspect; |
| 0u, // deUint32 baseMipLevel; |
| mipLevels, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| arraySize, // deUint32 arraySize; |
| } |
| }; |
| |
| for (deUint32 mipLevelNdx = 0; mipLevelNdx < mipLevels; mipLevelNdx++) |
| { |
| const VkExtent3D copyExtent = |
| { |
| imageExtent.width >> mipLevelNdx, |
| imageExtent.height >> mipLevelNdx, |
| imageExtent.depth |
| }; |
| |
| const bool isCompressed = isCompressedFormat(parms.format); |
| const deUint32 blockWidth = (isCompressed) ? getBlockWidth(parms.format) : 1u; |
| const deUint32 blockHeight = (isCompressed) ? getBlockHeight(parms.format) : 1u; |
| deUint32 rowLength = ((copyExtent.width + blockWidth-1) / blockWidth) * blockWidth; |
| deUint32 imageHeight = ((copyExtent.height + blockHeight-1) / blockHeight) * blockHeight; |
| |
| const VkBufferImageCopy copyRegion = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| rowLength, // deUint32 bufferRowLength; |
| imageHeight, // deUint32 bufferImageHeight; |
| { |
| getAspectFlags(imageAccess.getFormat()), // VkImageAspectFlags aspect; |
| mipLevelNdx, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arraySize, // deUint32 layerCount; |
| }, // VkImageSubresourceLayers imageSubresource; |
| { 0, 0, 0 }, // VkOffset3D imageOffset; |
| copyExtent // VkExtent3D imageExtent; |
| }; |
| |
| copyRegions.push_back(copyRegion); |
| } |
| |
| // Write buffer data |
| deMemcpy(bufferAlloc->getHostPtr(), imageAccess.getDataPtr(), bufferSize); |
| flushAlloc(vk, vkDevice, *bufferAlloc); |
| |
| // Copy buffer to image |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, |
| 1, &preBufferBarrier, (skipPreImageBarrier ? 0 : 1), (skipPreImageBarrier ? DE_NULL : &preImageBarrier)); |
| vk.cmdCopyBufferToImage(*m_cmdBuffer, *buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copyRegions.size(), ©Regions[0]); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| |
| submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer); |
| } |
| |
| void CopiesAndBlittingTestInstance::uploadImage (const tcu::ConstPixelBufferAccess& src, VkImage dst, const ImageParms& parms, const deUint32 mipLevels) |
| { |
| if (tcu::isCombinedDepthStencilType(src.getFormat().type)) |
| { |
| if (tcu::hasDepthComponent(src.getFormat().order)) |
| { |
| tcu::TextureLevel depthTexture (mapCombinedToDepthTransferFormat(src.getFormat()), src.getWidth(), src.getHeight(), src.getDepth()); |
| tcu::copy(depthTexture.getAccess(), tcu::getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_DEPTH)); |
| uploadImageAspect(depthTexture.getAccess(), dst, parms, mipLevels); |
| } |
| |
| if (tcu::hasStencilComponent(src.getFormat().order)) |
| { |
| tcu::TextureLevel stencilTexture (tcu::getEffectiveDepthStencilTextureFormat(src.getFormat(), tcu::Sampler::MODE_STENCIL), src.getWidth(), src.getHeight(), src.getDepth()); |
| tcu::copy(stencilTexture.getAccess(), tcu::getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_STENCIL)); |
| uploadImageAspect(stencilTexture.getAccess(), dst, parms, mipLevels); |
| } |
| } |
| else |
| uploadImageAspect(src, dst, parms, mipLevels); |
| } |
| |
| tcu::TestStatus CopiesAndBlittingTestInstance::checkTestResult (tcu::ConstPixelBufferAccess result) |
| { |
| const tcu::ConstPixelBufferAccess expected = m_expectedTextureLevel[0]->getAccess(); |
| |
| if (isFloatFormat(result.getFormat())) |
| { |
| const tcu::Vec4 threshold (0.0f); |
| if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expected, result, threshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| else |
| { |
| const tcu::UVec4 threshold (0u); |
| if (tcu::hasDepthComponent(result.getFormat().order) || tcu::hasStencilComponent(result.getFormat().order)) |
| { |
| if (!tcu::dsThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expected, result, 0.1f, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| else |
| { |
| if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expected, result, threshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| } |
| |
| return tcu::TestStatus::pass("CopiesAndBlitting test"); |
| } |
| |
| void CopiesAndBlittingTestInstance::generateExpectedResult (void) |
| { |
| const tcu::ConstPixelBufferAccess src = m_sourceTextureLevel->getAccess(); |
| const tcu::ConstPixelBufferAccess dst = m_destinationTextureLevel->getAccess(); |
| |
| m_expectedTextureLevel[0] = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth())); |
| tcu::copy(m_expectedTextureLevel[0]->getAccess(), dst); |
| |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| copyRegionToTextureLevel(src, m_expectedTextureLevel[0]->getAccess(), m_params.regions[i]); |
| } |
| |
| class CopiesAndBlittingTestCase : public vkt::TestCase |
| { |
| public: |
| CopiesAndBlittingTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description) |
| : vkt::TestCase (testCtx, name, description) |
| {} |
| |
| virtual TestInstance* createInstance (Context& context) const = 0; |
| }; |
| |
| void CopiesAndBlittingTestInstance::readImageAspect (vk::VkImage image, |
| const tcu::PixelBufferAccess& dst, |
| const ImageParms& imageParms, |
| const deUint32 mipLevel) |
| { |
| const InstanceInterface& vki = m_context.getInstanceInterface(); |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkPhysicalDevice physDevice = m_context.getPhysicalDevice(); |
| const VkDevice device = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| Allocator& allocator = m_context.getDefaultAllocator(); |
| |
| Move<VkBuffer> buffer; |
| de::MovePtr<Allocation> bufferAlloc; |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| const VkDeviceSize pixelDataSize = calculateSize(dst); |
| const VkExtent3D imageExtent = getExtent3D(imageParms, mipLevel); |
| |
| // Create destination buffer |
| { |
| const VkBufferCreateInfo bufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| pixelDataSize, // VkDeviceSize size; |
| VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| buffer = createBuffer(vk, device, &bufferParams); |
| bufferAlloc = allocateBuffer(vki, vk, physDevice, device, *buffer, MemoryRequirement::HostVisible, allocator, m_params.allocationKind); |
| VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset())); |
| |
| deMemset(bufferAlloc->getHostPtr(), 0, static_cast<size_t>(pixelDataSize)); |
| flushAlloc(vk, device, *bufferAlloc); |
| } |
| |
| // Barriers for copying image to buffer |
| const VkImageAspectFlags formatAspect = getAspectFlags(imageParms.format); |
| const VkImageMemoryBarrier imageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| imageParms.operationLayout, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| image, // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| formatAspect, // VkImageAspectFlags aspectMask; |
| mipLevel, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(imageParms)// deUint32 arraySize; |
| } |
| }; |
| |
| const VkBufferMemoryBarrier bufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *buffer, // VkBuffer buffer; |
| 0u, // VkDeviceSize offset; |
| pixelDataSize // VkDeviceSize size; |
| }; |
| |
| const VkImageMemoryBarrier postImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout oldLayout; |
| imageParms.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| image, // VkImage image; |
| { |
| formatAspect, // VkImageAspectFlags aspectMask; |
| mipLevel, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(imageParms) // deUint32 arraySize; |
| } // VkImageSubresourceRange subresourceRange; |
| }; |
| |
| // Copy image to buffer |
| const bool isCompressed = isCompressedFormat(imageParms.format); |
| const deUint32 blockWidth = (isCompressed) ? getBlockWidth(imageParms.format) : 1u; |
| const deUint32 blockHeight = (isCompressed) ? getBlockHeight(imageParms.format) : 1u; |
| deUint32 rowLength = ((imageExtent.width + blockWidth-1) / blockWidth) * blockWidth; |
| deUint32 imageHeight = ((imageExtent.height + blockHeight-1) / blockHeight) * blockHeight; |
| |
| // Copy image to buffer - note that there are cases where m_params.dst.image.format is not the same as dst.getFormat() |
| const VkImageAspectFlags aspect = isCompressedFormat(m_params.dst.image.format) ? |
| static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT) : getAspectFlags(dst.getFormat()); |
| const VkBufferImageCopy copyRegion = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| rowLength, // deUint32 bufferRowLength; |
| imageHeight, // deUint32 bufferImageHeight; |
| { |
| aspect, // VkImageAspectFlags aspect; |
| mipLevel, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| getArraySize(imageParms), // deUint32 layerCount; |
| }, // VkImageSubresourceLayers imageSubresource; |
| { 0, 0, 0 }, // VkOffset3D imageOffset; |
| imageExtent // VkExtent3D imageExtent; |
| }; |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier); |
| vk.cmdCopyImageToBuffer(*m_cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1u, ©Region); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT|VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 1, &postImageBarrier); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| |
| submitCommandsAndWait(vk, device, queue, *m_cmdBuffer); |
| |
| // Read buffer data |
| invalidateAlloc(vk, device, *bufferAlloc); |
| tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferAlloc->getHostPtr())); |
| } |
| |
| de::MovePtr<tcu::TextureLevel> CopiesAndBlittingTestInstance::readImage (vk::VkImage image, |
| const ImageParms& parms, |
| const deUint32 mipLevel) |
| { |
| const tcu::TextureFormat imageFormat = getSizeCompatibleTcuTextureFormat(parms.format); |
| de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(imageFormat, parms.extent.width >> mipLevel, parms.extent.height >> mipLevel, parms.extent.depth)); |
| |
| if (tcu::isCombinedDepthStencilType(imageFormat.type)) |
| { |
| if (tcu::hasDepthComponent(imageFormat.order)) |
| { |
| tcu::TextureLevel depthTexture (mapCombinedToDepthTransferFormat(imageFormat), parms.extent.width >> mipLevel, parms.extent.height >> mipLevel, parms.extent.depth); |
| readImageAspect(image, depthTexture.getAccess(), parms, mipLevel); |
| tcu::copy(tcu::getEffectiveDepthStencilAccess(resultLevel->getAccess(), tcu::Sampler::MODE_DEPTH), depthTexture.getAccess()); |
| } |
| |
| if (tcu::hasStencilComponent(imageFormat.order)) |
| { |
| tcu::TextureLevel stencilTexture (tcu::getEffectiveDepthStencilTextureFormat(imageFormat, tcu::Sampler::MODE_STENCIL), parms.extent.width >> mipLevel, parms.extent.height >> mipLevel, parms.extent.depth); |
| readImageAspect(image, stencilTexture.getAccess(), parms, mipLevel); |
| tcu::copy(tcu::getEffectiveDepthStencilAccess(resultLevel->getAccess(), tcu::Sampler::MODE_STENCIL), stencilTexture.getAccess()); |
| } |
| } |
| else |
| readImageAspect(image, resultLevel->getAccess(), parms, mipLevel); |
| |
| return resultLevel; |
| } |
| |
| // Copy from image to image. |
| |
| class CopyImageToImage : public CopiesAndBlittingTestInstance |
| { |
| public: |
| CopyImageToImage (Context& context, |
| TestParams params); |
| virtual tcu::TestStatus iterate (void); |
| |
| protected: |
| virtual tcu::TestStatus checkTestResult (tcu::ConstPixelBufferAccess result = tcu::ConstPixelBufferAccess()); |
| |
| private: |
| Move<VkImage> m_source; |
| de::MovePtr<Allocation> m_sourceImageAlloc; |
| Move<VkImage> m_destination; |
| de::MovePtr<Allocation> m_destinationImageAlloc; |
| |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel = 0u); |
| }; |
| |
| CopyImageToImage::CopyImageToImage (Context& context, TestParams params) |
| : CopiesAndBlittingTestInstance(context, params) |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = context.getPhysicalDevice(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = context.getDefaultAllocator(); |
| |
| // Create source image |
| { |
| const VkImageCreateInfo sourceImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.src.image), // VkImageCreateFlags flags; |
| m_params.src.image.imageType, // VkImageType imageType; |
| m_params.src.image.format, // VkFormat format; |
| getExtent3D(m_params.src.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.src.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_source = createImage(vk, vkDevice, &sourceImageParams); |
| m_sourceImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_source, m_sourceImageAlloc->getMemory(), m_sourceImageAlloc->getOffset())); |
| } |
| |
| // Create destination image |
| { |
| const VkImageCreateInfo destinationImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.dst.image), // VkImageCreateFlags flags; |
| m_params.dst.image.imageType, // VkImageType imageType; |
| m_params.dst.image.format, // VkFormat format; |
| getExtent3D(m_params.dst.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.dst.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_destination = createImage(vk, vkDevice, &destinationImageParams); |
| m_destinationImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset())); |
| } |
| } |
| |
| tcu::TestStatus CopyImageToImage::iterate (void) |
| { |
| const bool srcCompressed = isCompressedFormat(m_params.src.image.format); |
| const bool dstCompressed = isCompressedFormat(m_params.dst.image.format); |
| |
| const tcu::TextureFormat srcTcuFormat = getSizeCompatibleTcuTextureFormat(m_params.src.image.format); |
| const tcu::TextureFormat dstTcuFormat = getSizeCompatibleTcuTextureFormat(m_params.dst.image.format); |
| |
| m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(srcTcuFormat, |
| (int)m_params.src.image.extent.width, |
| (int)m_params.src.image.extent.height, |
| (int)m_params.src.image.extent.depth)); |
| generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.src.image.extent.depth, FILL_MODE_GRADIENT); |
| m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dstTcuFormat, |
| (int)m_params.dst.image.extent.width, |
| (int)m_params.dst.image.extent.height, |
| (int)m_params.dst.image.extent.depth)); |
| generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth, m_params.clearDestination ? FILL_MODE_WHITE : FILL_MODE_GRADIENT); |
| generateExpectedResult(); |
| |
| uploadImage(m_sourceTextureLevel->getAccess(), m_source.get(), m_params.src.image); |
| uploadImage(m_destinationTextureLevel->getAccess(), m_destination.get(), m_params.dst.image); |
| |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| std::vector<VkImageCopy> imageCopies; |
| std::vector<VkImageCopy2KHR> imageCopies2KHR; |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| VkImageCopy imageCopy = m_params.regions[i].imageCopy; |
| |
| // When copying between compressed and uncompressed formats the extent |
| // members represent the texel dimensions of the source image. |
| if (srcCompressed) |
| { |
| const deUint32 blockWidth = getBlockWidth(m_params.src.image.format); |
| const deUint32 blockHeight = getBlockHeight(m_params.src.image.format); |
| |
| imageCopy.srcOffset.x *= blockWidth; |
| imageCopy.srcOffset.y *= blockHeight; |
| imageCopy.extent.width *= blockWidth; |
| imageCopy.extent.height *= blockHeight; |
| } |
| |
| if (dstCompressed) |
| { |
| const deUint32 blockWidth = getBlockWidth(m_params.dst.image.format); |
| const deUint32 blockHeight = getBlockHeight(m_params.dst.image.format); |
| |
| imageCopy.dstOffset.x *= blockWidth; |
| imageCopy.dstOffset.y *= blockHeight; |
| } |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| imageCopies.push_back(imageCopy); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| imageCopies2KHR.push_back(convertvkImageCopyTovkImageCopy2KHR(imageCopy)); |
| } |
| } |
| |
| const VkImageMemoryBarrier imageBarriers[] = |
| { |
| // source image |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| m_params.src.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_source.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(srcTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.src.image)// deUint32 arraySize; |
| } |
| }, |
| // destination image |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| m_params.dst.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.dst.image)// deUint32 arraySize; |
| } |
| }, |
| }; |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers); |
| |
| if (m_params.clearDestination) |
| { |
| VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }; |
| VkClearColorValue clearColor; |
| |
| clearColor.float32[0] = 1.0f; |
| clearColor.float32[1] = 1.0f; |
| clearColor.float32[2] = 1.0f; |
| clearColor.float32[3] = 1.0f; |
| vk.cmdClearColorImage(*m_cmdBuffer, m_destination.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &range); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers); |
| } |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdCopyImage(*m_cmdBuffer, m_source.get(), m_params.src.image.operationLayout, m_destination.get(), m_params.dst.image.operationLayout, (deUint32)imageCopies.size(), imageCopies.data()); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkCopyImageInfo2KHR copyImageInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_source.get(), // VkImage srcImage; |
| m_params.src.image.operationLayout, // VkImageLayout srcImageLayout; |
| m_destination.get(), // VkImage dstImage; |
| m_params.dst.image.operationLayout, // VkImageLayout dstImageLayout; |
| (deUint32)imageCopies2KHR.size(), // uint32_t regionCount; |
| imageCopies2KHR.data() // const VkImageCopy2KHR* pRegions; |
| }; |
| |
| vk.cmdCopyImage2(*m_cmdBuffer, ©ImageInfo2KHR); |
| } |
| |
| endCommandBuffer(vk, *m_cmdBuffer); |
| |
| submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer); |
| |
| de::MovePtr<tcu::TextureLevel> resultTextureLevel = readImage(*m_destination, m_params.dst.image); |
| |
| return checkTestResult(resultTextureLevel->getAccess()); |
| } |
| |
| tcu::TestStatus CopyImageToImage::checkTestResult (tcu::ConstPixelBufferAccess result) |
| { |
| const tcu::Vec4 fThreshold (0.0f); |
| const tcu::UVec4 uThreshold (0u); |
| |
| if (tcu::isCombinedDepthStencilType(result.getFormat().type)) |
| { |
| if (tcu::hasDepthComponent(result.getFormat().order)) |
| { |
| const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_DEPTH; |
| const tcu::ConstPixelBufferAccess depthResult = tcu::getEffectiveDepthStencilAccess(result, mode); |
| const tcu::ConstPixelBufferAccess expectedResult = tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[0]->getAccess(), mode); |
| |
| if (isFloatFormat(result.getFormat())) |
| { |
| if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, depthResult, fThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| else |
| { |
| if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, depthResult, uThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| } |
| |
| if (tcu::hasStencilComponent(result.getFormat().order)) |
| { |
| const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_STENCIL; |
| const tcu::ConstPixelBufferAccess stencilResult = tcu::getEffectiveDepthStencilAccess(result, mode); |
| const tcu::ConstPixelBufferAccess expectedResult = tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[0]->getAccess(), mode); |
| |
| if (isFloatFormat(result.getFormat())) |
| { |
| if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, stencilResult, fThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| else |
| { |
| if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, stencilResult, uThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| } |
| } |
| else |
| { |
| if (isFloatFormat(result.getFormat())) |
| { |
| if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", m_expectedTextureLevel[0]->getAccess(), result, fThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| else |
| { |
| if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", m_expectedTextureLevel[0]->getAccess(), result, uThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| } |
| |
| return tcu::TestStatus::pass("CopiesAndBlitting test"); |
| } |
| |
| void CopyImageToImage::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel) |
| { |
| DE_UNREF(mipLevel); |
| |
| VkOffset3D srcOffset = region.imageCopy.srcOffset; |
| VkOffset3D dstOffset = region.imageCopy.dstOffset; |
| VkExtent3D extent = region.imageCopy.extent; |
| |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_3D && m_params.dst.image.imageType == VK_IMAGE_TYPE_2D) |
| { |
| dstOffset.z = srcOffset.z; |
| extent.depth = std::max(region.imageCopy.extent.depth, region.imageCopy.dstSubresource.layerCount); |
| } |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_2D && m_params.dst.image.imageType == VK_IMAGE_TYPE_3D) |
| { |
| srcOffset.z = dstOffset.z; |
| extent.depth = std::max(region.imageCopy.extent.depth, region.imageCopy.srcSubresource.layerCount); |
| } |
| |
| |
| if (tcu::isCombinedDepthStencilType(src.getFormat().type)) |
| { |
| DE_ASSERT(src.getFormat() == dst.getFormat()); |
| |
| // Copy depth. |
| if (tcu::hasDepthComponent(src.getFormat().order)) |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_DEPTH); |
| const tcu::PixelBufferAccess dstSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_DEPTH); |
| tcu::copy(dstSubRegion, srcSubRegion); |
| } |
| |
| // Copy stencil. |
| if (tcu::hasStencilComponent(src.getFormat().order)) |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_STENCIL); |
| const tcu::PixelBufferAccess dstSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_STENCIL); |
| tcu::copy(dstSubRegion, srcSubRegion); |
| } |
| } |
| else |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth); |
| // CopyImage acts like a memcpy. Replace the destination format with the srcformat to use a memcpy. |
| const tcu::PixelBufferAccess dstWithSrcFormat (srcSubRegion.getFormat(), dst.getSize(), dst.getDataPtr()); |
| const tcu::PixelBufferAccess dstSubRegion = tcu::getSubregion(dstWithSrcFormat, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth); |
| |
| tcu::copy(dstSubRegion, srcSubRegion); |
| } |
| } |
| |
| class CopyImageToImageTestCase : public vkt::TestCase |
| { |
| public: |
| CopyImageToImageTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams params) |
| : vkt::TestCase (testCtx, name, description) |
| , m_params (params) |
| {} |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new CopyImageToImage(context, m_params); |
| } |
| |
| virtual void checkSupport (Context& context) const |
| { |
| if (m_params.allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation")) |
| TCU_THROW(NotSupportedError, "VK_KHR_dedicated_allocation is not supported"); |
| } |
| |
| if (m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_copy_commands2")) |
| TCU_THROW(NotSupportedError, "VK_KHR_copy_commands2 is not supported"); |
| } |
| |
| if (m_params.separateDepthStencilLayouts) |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_separate_depth_stencil_layouts")) |
| TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported"); |
| |
| if ((m_params.dst.image.imageType == VK_IMAGE_TYPE_3D && m_params.src.image.imageType == VK_IMAGE_TYPE_2D) || |
| (m_params.dst.image.imageType == VK_IMAGE_TYPE_2D && m_params.src.image.imageType == VK_IMAGE_TYPE_3D)) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance1")) |
| TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported"); |
| } |
| |
| const VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits; |
| VkImageFormatProperties properties; |
| |
| if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.src.image.format, |
| m_params.src.image.imageType, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT, |
| 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) || |
| (context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.dst.image.format, |
| m_params.dst.image.imageType, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, |
| 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED)) |
| { |
| TCU_THROW(NotSupportedError, "Format not supported"); |
| } |
| |
| // Check maxImageDimension1D |
| { |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_1D && m_params.src.image.extent.width > limits.maxImageDimension1D) |
| TCU_THROW(NotSupportedError, "Requested 1D src image dimensions not supported"); |
| |
| if (m_params.dst.image.imageType == VK_IMAGE_TYPE_1D && m_params.dst.image.extent.width > limits.maxImageDimension1D) |
| TCU_THROW(NotSupportedError, "Requested 1D dst image dimensions not supported"); |
| } |
| |
| // Check maxImageDimension2D |
| { |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_2D && (m_params.src.image.extent.width > limits.maxImageDimension2D |
| || m_params.src.image.extent.height > limits.maxImageDimension2D)) |
| { |
| TCU_THROW(NotSupportedError, "Requested 2D src image dimensions not supported"); |
| } |
| |
| if (m_params.dst.image.imageType == VK_IMAGE_TYPE_2D && (m_params.dst.image.extent.width > limits.maxImageDimension2D |
| || m_params.dst.image.extent.height > limits.maxImageDimension2D)) |
| { |
| TCU_THROW(NotSupportedError, "Requested 2D dst image dimensions not supported"); |
| } |
| } |
| |
| // Check maxImageDimension3D |
| { |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_3D && (m_params.src.image.extent.width > limits.maxImageDimension3D |
| || m_params.src.image.extent.height > limits.maxImageDimension3D |
| || m_params.src.image.extent.depth > limits.maxImageDimension3D)) |
| { |
| TCU_THROW(NotSupportedError, "Requested 3D src image dimensions not supported"); |
| } |
| |
| if (m_params.dst.image.imageType == VK_IMAGE_TYPE_3D && (m_params.dst.image.extent.width > limits.maxImageDimension3D |
| || m_params.dst.image.extent.height > limits.maxImageDimension3D |
| || m_params.src.image.extent.depth > limits.maxImageDimension3D)) |
| { |
| TCU_THROW(NotSupportedError, "Requested 3D dst image dimensions not supported"); |
| } |
| } |
| } |
| |
| private: |
| TestParams m_params; |
| }; |
| |
| class CopyImageToImageMipmap : public CopiesAndBlittingTestInstance |
| { |
| public: |
| CopyImageToImageMipmap (Context& context, |
| TestParams params); |
| virtual tcu::TestStatus iterate (void); |
| |
| protected: |
| tcu::TestStatus checkResult (tcu::ConstPixelBufferAccess result, tcu::ConstPixelBufferAccess expected); |
| |
| private: |
| Move<VkImage> m_source; |
| de::MovePtr<Allocation> m_sourceImageAlloc; |
| Move<VkImage> m_destination; |
| de::MovePtr<Allocation> m_destinationImageAlloc; |
| |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel = 0u); |
| |
| }; |
| |
| CopyImageToImageMipmap::CopyImageToImageMipmap (Context& context, TestParams params) |
| : CopiesAndBlittingTestInstance(context, params) |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = context.getPhysicalDevice(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = context.getDefaultAllocator(); |
| |
| // Create source image |
| { |
| const VkImageCreateInfo sourceImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.src.image), // VkImageCreateFlags flags; |
| m_params.src.image.imageType, // VkImageType imageType; |
| m_params.src.image.format, // VkFormat format; |
| getExtent3D(m_params.src.image), // VkExtent3D extent; |
| params.mipLevels, // deUint32 mipLevels; |
| getArraySize(m_params.src.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_source = createImage(vk, vkDevice, &sourceImageParams); |
| m_sourceImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_source, m_sourceImageAlloc->getMemory(), m_sourceImageAlloc->getOffset())); |
| } |
| |
| // Create destination image |
| { |
| const VkImageCreateInfo destinationImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.dst.image), // VkImageCreateFlags flags; |
| m_params.dst.image.imageType, // VkImageType imageType; |
| m_params.dst.image.format, // VkFormat format; |
| getExtent3D(m_params.dst.image), // VkExtent3D extent; |
| params.mipLevels, // deUint32 mipLevels; |
| getArraySize(m_params.dst.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_destination = createImage(vk, vkDevice, &destinationImageParams); |
| m_destinationImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset())); |
| } |
| } |
| |
| tcu::TestStatus CopyImageToImageMipmap::iterate (void) |
| { |
| const bool srcCompressed = isCompressedFormat(m_params.src.image.format); |
| const bool dstCompressed = isCompressedFormat(m_params.dst.image.format); |
| |
| const tcu::TextureFormat srcTcuFormat = getSizeCompatibleTcuTextureFormat(m_params.src.image.format); |
| const tcu::TextureFormat dstTcuFormat = getSizeCompatibleTcuTextureFormat(m_params.dst.image.format); |
| |
| m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(srcTcuFormat, |
| (int)m_params.src.image.extent.width, |
| (int)m_params.src.image.extent.height, |
| (int)m_params.src.image.extent.depth)); |
| generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.src.image.extent.depth, FILL_MODE_GRADIENT); |
| uploadImage(m_sourceTextureLevel->getAccess(), m_source.get(), m_params.src.image, m_params.mipLevels); |
| |
| m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dstTcuFormat, |
| (int)m_params.dst.image.extent.width, |
| (int)m_params.dst.image.extent.height, |
| (int)m_params.dst.image.extent.depth)); |
| generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth, FILL_MODE_RED); |
| uploadImage(m_destinationTextureLevel->getAccess(), m_destination.get(), m_params.dst.image, m_params.mipLevels); |
| |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| std::vector<VkImageCopy> imageCopies; |
| std::vector<VkImageCopy2KHR> imageCopies2KHR; |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| VkImageCopy imageCopy = m_params.regions[i].imageCopy; |
| |
| // When copying between compressed and uncompressed formats the extent |
| // members represent the texel dimensions of the source image. |
| if (srcCompressed) |
| { |
| const deUint32 blockWidth = getBlockWidth(m_params.src.image.format); |
| const deUint32 blockHeight = getBlockHeight(m_params.src.image.format); |
| |
| imageCopy.srcOffset.x *= blockWidth; |
| imageCopy.srcOffset.y *= blockHeight; |
| imageCopy.extent.width *= blockWidth; |
| imageCopy.extent.height *= blockHeight; |
| } |
| |
| if (dstCompressed) |
| { |
| const deUint32 blockWidth = getBlockWidth(m_params.dst.image.format); |
| const deUint32 blockHeight = getBlockHeight(m_params.dst.image.format); |
| |
| imageCopy.dstOffset.x *= blockWidth; |
| imageCopy.dstOffset.y *= blockHeight; |
| } |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| imageCopies.push_back(imageCopy); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| imageCopies2KHR.push_back(convertvkImageCopyTovkImageCopy2KHR(imageCopy)); |
| } |
| } |
| |
| const VkImageMemoryBarrier imageBarriers[] = |
| { |
| // source image |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| m_params.src.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_source.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(srcTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| m_params.mipLevels, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.src.image)// deUint32 arraySize; |
| } |
| }, |
| // destination image |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| m_params.dst.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| m_params.mipLevels, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.dst.image)// deUint32 arraySize; |
| } |
| }, |
| }; |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdCopyImage(*m_cmdBuffer, m_source.get(), m_params.src.image.operationLayout, m_destination.get(), m_params.dst.image.operationLayout, (deUint32)imageCopies.size(), imageCopies.data()); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkCopyImageInfo2KHR copyImageInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_source.get(), // VkImage srcImage; |
| m_params.src.image.operationLayout, // VkImageLayout srcImageLayout; |
| m_destination.get(), // VkImage dstImage; |
| m_params.dst.image.operationLayout, // VkImageLayout dstImageLayout; |
| (deUint32)imageCopies2KHR.size(), // uint32_t regionCount; |
| imageCopies2KHR.data() // const VkImageCopy2KHR* pRegions; |
| }; |
| |
| vk.cmdCopyImage2(*m_cmdBuffer, ©ImageInfo2KHR); |
| } |
| |
| endCommandBuffer(vk, *m_cmdBuffer); |
| |
| submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer); |
| |
| for (deUint32 miplevel = 0; miplevel < m_params.mipLevels; miplevel++) |
| { |
| de::MovePtr<tcu::TextureLevel> resultTextureLevel = readImage(*m_destination, m_params.dst.image, miplevel); |
| de::MovePtr<tcu::TextureLevel> expectedTextureLevel = readImage(*m_source, m_params.src.image, miplevel); |
| |
| tcu::TestStatus result = checkResult(resultTextureLevel->getAccess(), expectedTextureLevel->getAccess()); |
| if (result.getCode() != QP_TEST_RESULT_PASS) |
| return result; |
| } |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| tcu::TestStatus CopyImageToImageMipmap::checkResult (tcu::ConstPixelBufferAccess result, tcu::ConstPixelBufferAccess expected) |
| { |
| const tcu::Vec4 fThreshold (0.0f); |
| const tcu::UVec4 uThreshold (0u); |
| |
| if (tcu::isCombinedDepthStencilType(result.getFormat().type)) |
| { |
| if (tcu::hasDepthComponent(result.getFormat().order)) |
| { |
| const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_DEPTH; |
| const tcu::ConstPixelBufferAccess depthResult = tcu::getEffectiveDepthStencilAccess(result, mode); |
| const tcu::ConstPixelBufferAccess expectedResult = tcu::getEffectiveDepthStencilAccess(expected, mode); |
| |
| if (isFloatFormat(result.getFormat())) |
| { |
| if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, depthResult, fThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| else |
| { |
| if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, depthResult, uThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| } |
| |
| if (tcu::hasStencilComponent(result.getFormat().order)) |
| { |
| const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_STENCIL; |
| const tcu::ConstPixelBufferAccess stencilResult = tcu::getEffectiveDepthStencilAccess(result, mode); |
| const tcu::ConstPixelBufferAccess expectedResult = tcu::getEffectiveDepthStencilAccess(expected, mode); |
| |
| if (isFloatFormat(result.getFormat())) |
| { |
| if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, stencilResult, fThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| else |
| { |
| if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, stencilResult, uThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| } |
| } |
| else |
| { |
| if (isFloatFormat(result.getFormat())) |
| { |
| if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expected, result, fThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| else if (isSnormFormat(mapTextureFormat(result.getFormat()))) |
| { |
| // There may be an ambiguity between two possible binary representations of 1.0. |
| // Get rid of that by expanding the data to floats and re-normalizing again. |
| |
| tcu::TextureLevel resultSnorm (result.getFormat(), result.getWidth(), result.getHeight(), result.getDepth()); |
| { |
| tcu::TextureLevel resultFloat (tcu::TextureFormat(resultSnorm.getFormat().order, tcu::TextureFormat::FLOAT), resultSnorm.getWidth(), resultSnorm.getHeight(), resultSnorm.getDepth()); |
| |
| tcu::copy(resultFloat.getAccess(), result); |
| tcu::copy(resultSnorm, resultFloat.getAccess()); |
| } |
| |
| tcu::TextureLevel expectedSnorm (expected.getFormat(), expected.getWidth(), expected.getHeight(), expected.getDepth()); |
| |
| { |
| tcu::TextureLevel expectedFloat (tcu::TextureFormat(expectedSnorm.getFormat().order, tcu::TextureFormat::FLOAT), expectedSnorm.getWidth(), expectedSnorm.getHeight(), expectedSnorm.getDepth()); |
| |
| tcu::copy(expectedFloat.getAccess(), m_expectedTextureLevel[0]->getAccess()); |
| tcu::copy(expectedSnorm, expectedFloat.getAccess()); |
| } |
| |
| if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedSnorm.getAccess(), resultSnorm.getAccess(), uThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| else |
| { |
| if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expected, result, uThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| } |
| |
| return tcu::TestStatus::pass("CopiesAndBlitting test"); |
| } |
| |
| void CopyImageToImageMipmap::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel) |
| { |
| DE_UNREF(mipLevel); |
| |
| VkOffset3D srcOffset = region.imageCopy.srcOffset; |
| VkOffset3D dstOffset = region.imageCopy.dstOffset; |
| VkExtent3D extent = region.imageCopy.extent; |
| |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_3D && m_params.dst.image.imageType == VK_IMAGE_TYPE_2D) |
| { |
| dstOffset.z = srcOffset.z; |
| extent.depth = std::max(region.imageCopy.extent.depth, region.imageCopy.dstSubresource.layerCount); |
| } |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_2D && m_params.dst.image.imageType == VK_IMAGE_TYPE_3D) |
| { |
| srcOffset.z = dstOffset.z; |
| extent.depth = std::max(region.imageCopy.extent.depth, region.imageCopy.srcSubresource.layerCount); |
| } |
| |
| |
| if (tcu::isCombinedDepthStencilType(src.getFormat().type)) |
| { |
| DE_ASSERT(src.getFormat() == dst.getFormat()); |
| |
| // Copy depth. |
| if (tcu::hasDepthComponent(src.getFormat().order)) |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_DEPTH); |
| const tcu::PixelBufferAccess dstSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_DEPTH); |
| tcu::copy(dstSubRegion, srcSubRegion); |
| } |
| |
| // Copy stencil. |
| if (tcu::hasStencilComponent(src.getFormat().order)) |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_STENCIL); |
| const tcu::PixelBufferAccess dstSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_STENCIL); |
| tcu::copy(dstSubRegion, srcSubRegion); |
| } |
| } |
| else |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth); |
| // CopyImage acts like a memcpy. Replace the destination format with the srcformat to use a memcpy. |
| const tcu::PixelBufferAccess dstWithSrcFormat (srcSubRegion.getFormat(), dst.getSize(), dst.getDataPtr()); |
| const tcu::PixelBufferAccess dstSubRegion = tcu::getSubregion(dstWithSrcFormat, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth); |
| |
| tcu::copy(dstSubRegion, srcSubRegion); |
| } |
| } |
| |
| class CopyImageToImageMipmapTestCase : public vkt::TestCase |
| { |
| public: |
| CopyImageToImageMipmapTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams params) |
| : vkt::TestCase (testCtx, name, description) |
| , m_params (params) |
| {} |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new CopyImageToImageMipmap(context, m_params); |
| } |
| |
| virtual void checkSupport (Context& context) const |
| { |
| if (m_params.allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation")) |
| TCU_THROW(NotSupportedError, "VK_KHR_dedicated_allocation is not supported"); |
| } |
| |
| if (m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_copy_commands2")) |
| TCU_THROW(NotSupportedError, "VK_KHR_copy_commands2 is not supported"); |
| } |
| |
| if (m_params.separateDepthStencilLayouts) |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_separate_depth_stencil_layouts")) |
| TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported"); |
| |
| if ((m_params.dst.image.imageType == VK_IMAGE_TYPE_3D && m_params.src.image.imageType == VK_IMAGE_TYPE_2D) || |
| (m_params.dst.image.imageType == VK_IMAGE_TYPE_2D && m_params.src.image.imageType == VK_IMAGE_TYPE_3D)) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance1")) |
| TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported"); |
| } |
| |
| const VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits; |
| VkImageFormatProperties properties; |
| |
| if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.src.image.format, |
| m_params.src.image.imageType, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT, |
| 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) || |
| (context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.dst.image.format, |
| m_params.dst.image.imageType, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, |
| 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED)) |
| { |
| TCU_THROW(NotSupportedError, "Format not supported"); |
| } |
| |
| // Check maxImageDimension1D |
| { |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_1D && m_params.src.image.extent.width > limits.maxImageDimension1D) |
| TCU_THROW(NotSupportedError, "Requested 1D src image dimensions not supported"); |
| |
| if (m_params.dst.image.imageType == VK_IMAGE_TYPE_1D && m_params.dst.image.extent.width > limits.maxImageDimension1D) |
| TCU_THROW(NotSupportedError, "Requested 1D dst image dimensions not supported"); |
| } |
| |
| // Check maxImageDimension2D |
| { |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_2D && (m_params.src.image.extent.width > limits.maxImageDimension2D |
| || m_params.src.image.extent.height > limits.maxImageDimension2D)) |
| { |
| TCU_THROW(NotSupportedError, "Requested 2D src image dimensions not supported"); |
| } |
| |
| if (m_params.dst.image.imageType == VK_IMAGE_TYPE_2D && (m_params.dst.image.extent.width > limits.maxImageDimension2D |
| || m_params.dst.image.extent.height > limits.maxImageDimension2D)) |
| { |
| TCU_THROW(NotSupportedError, "Requested 2D dst image dimensions not supported"); |
| } |
| } |
| |
| // Check maxImageDimension3D |
| { |
| if (m_params.src.image.imageType == VK_IMAGE_TYPE_3D && (m_params.src.image.extent.width > limits.maxImageDimension3D |
| || m_params.src.image.extent.height > limits.maxImageDimension3D |
| || m_params.src.image.extent.depth > limits.maxImageDimension3D)) |
| { |
| TCU_THROW(NotSupportedError, "Requested 3D src image dimensions not supported"); |
| } |
| |
| if (m_params.dst.image.imageType == VK_IMAGE_TYPE_3D && (m_params.dst.image.extent.width > limits.maxImageDimension3D |
| || m_params.dst.image.extent.height > limits.maxImageDimension3D |
| || m_params.src.image.extent.depth > limits.maxImageDimension3D)) |
| { |
| TCU_THROW(NotSupportedError, "Requested 3D dst image dimensions not supported"); |
| } |
| } |
| } |
| |
| private: |
| TestParams m_params; |
| }; |
| |
| // Copy from buffer to buffer. |
| |
| class CopyBufferToBuffer : public CopiesAndBlittingTestInstance |
| { |
| public: |
| CopyBufferToBuffer (Context& context, TestParams params); |
| virtual tcu::TestStatus iterate (void); |
| private: |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess, tcu::PixelBufferAccess, CopyRegion, deUint32 mipLevel = 0u); |
| Move<VkBuffer> m_source; |
| de::MovePtr<Allocation> m_sourceBufferAlloc; |
| Move<VkBuffer> m_destination; |
| de::MovePtr<Allocation> m_destinationBufferAlloc; |
| }; |
| |
| CopyBufferToBuffer::CopyBufferToBuffer (Context& context, TestParams params) |
| : CopiesAndBlittingTestInstance (context, params) |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = context.getPhysicalDevice(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = context.getDefaultAllocator(); |
| |
| // Create source buffer |
| { |
| const VkBufferCreateInfo sourceBufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| m_params.src.buffer.size, // VkDeviceSize size; |
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| m_source = createBuffer(vk, vkDevice, &sourceBufferParams); |
| m_sourceBufferAlloc = allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *m_source, m_sourceBufferAlloc->getMemory(), m_sourceBufferAlloc->getOffset())); |
| } |
| |
| // Create destination buffer |
| { |
| const VkBufferCreateInfo destinationBufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| m_params.dst.buffer.size, // VkDeviceSize size; |
| VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| m_destination = createBuffer(vk, vkDevice, &destinationBufferParams); |
| m_destinationBufferAlloc = allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *m_destination, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset())); |
| } |
| } |
| |
| tcu::TestStatus CopyBufferToBuffer::iterate (void) |
| { |
| const int srcLevelWidth = (int)(m_params.src.buffer.size/4); // Here the format is VK_FORMAT_R32_UINT, we need to divide the buffer size by 4 |
| m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R32_UINT), srcLevelWidth, 1)); |
| generateBuffer(m_sourceTextureLevel->getAccess(), srcLevelWidth, 1, 1, FILL_MODE_RED); |
| |
| const int dstLevelWidth = (int)(m_params.dst.buffer.size/4); |
| m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R32_UINT), dstLevelWidth, 1)); |
| generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1, FILL_MODE_BLACK); |
| |
| generateExpectedResult(); |
| |
| uploadBuffer(m_sourceTextureLevel->getAccess(), *m_sourceBufferAlloc); |
| uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc); |
| |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| const VkBufferMemoryBarrier srcBufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *m_source, // VkBuffer buffer; |
| 0u, // VkDeviceSize offset; |
| m_params.src.buffer.size // VkDeviceSize size; |
| }; |
| |
| const VkBufferMemoryBarrier dstBufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *m_destination, // VkBuffer buffer; |
| 0u, // VkDeviceSize offset; |
| m_params.dst.buffer.size // VkDeviceSize size; |
| }; |
| |
| std::vector<VkBufferCopy> bufferCopies; |
| std::vector<VkBufferCopy2KHR> bufferCopies2KHR; |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| bufferCopies.push_back(m_params.regions[i].bufferCopy); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| bufferCopies2KHR.push_back(convertvkBufferCopyTovkBufferCopy2KHR(m_params.regions[i].bufferCopy)); |
| } |
| } |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &srcBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdCopyBuffer(*m_cmdBuffer, m_source.get(), m_destination.get(), (deUint32)m_params.regions.size(), &bufferCopies[0]); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkCopyBufferInfo2KHR copyBufferInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_source.get(), // VkBuffer srcBuffer; |
| m_destination.get(), // VkBuffer dstBuffer; |
| (deUint32)m_params.regions.size(), // uint32_t regionCount; |
| &bufferCopies2KHR[0] // const VkBufferCopy2KHR* pRegions; |
| }; |
| |
| vk.cmdCopyBuffer2(*m_cmdBuffer, ©BufferInfo2KHR); |
| } |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer); |
| |
| // Read buffer data |
| de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R32_UINT), dstLevelWidth, 1)); |
| invalidateAlloc(vk, vkDevice, *m_destinationBufferAlloc); |
| tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr())); |
| |
| return checkTestResult(resultLevel->getAccess()); |
| } |
| |
| void CopyBufferToBuffer::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel) |
| { |
| DE_UNREF(mipLevel); |
| |
| deMemcpy((deUint8*) dst.getDataPtr() + region.bufferCopy.dstOffset, |
| (deUint8*) src.getDataPtr() + region.bufferCopy.srcOffset, |
| (size_t)region.bufferCopy.size); |
| } |
| |
| class BufferToBufferTestCase : public vkt::TestCase |
| { |
| public: |
| BufferToBufferTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams params) |
| : vkt::TestCase (testCtx, name, description) |
| , m_params (params) |
| {} |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new CopyBufferToBuffer(context, m_params); |
| } |
| |
| virtual void checkSupport(Context& context) const |
| { |
| if (m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_copy_commands2")) |
| { |
| TCU_THROW(NotSupportedError, "VK_KHR_copy_commands2 is not supported"); |
| } |
| } |
| } |
| |
| private: |
| TestParams m_params; |
| }; |
| |
| // Copy from image to buffer. |
| |
| class CopyImageToBuffer : public CopiesAndBlittingTestInstance |
| { |
| public: |
| CopyImageToBuffer (Context& context, |
| TestParams testParams); |
| virtual tcu::TestStatus iterate (void); |
| private: |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel = 0u); |
| |
| tcu::TextureFormat m_textureFormat; |
| VkDeviceSize m_bufferSize; |
| |
| Move<VkImage> m_source; |
| de::MovePtr<Allocation> m_sourceImageAlloc; |
| Move<VkBuffer> m_destination; |
| de::MovePtr<Allocation> m_destinationBufferAlloc; |
| }; |
| |
| CopyImageToBuffer::CopyImageToBuffer (Context& context, TestParams testParams) |
| : CopiesAndBlittingTestInstance(context, testParams) |
| , m_textureFormat(mapVkFormat(testParams.src.image.format)) |
| , m_bufferSize(m_params.dst.buffer.size * tcu::getPixelSize(m_textureFormat)) |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = context.getPhysicalDevice(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = context.getDefaultAllocator(); |
| |
| // Create source image |
| { |
| const VkImageCreateInfo sourceImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.src.image), // VkImageCreateFlags flags; |
| m_params.src.image.imageType, // VkImageType imageType; |
| m_params.src.image.format, // VkFormat format; |
| getExtent3D(m_params.src.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.src.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_source = createImage(vk, vkDevice, &sourceImageParams); |
| m_sourceImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_source, m_sourceImageAlloc->getMemory(), m_sourceImageAlloc->getOffset())); |
| } |
| |
| // Create destination buffer |
| { |
| const VkBufferCreateInfo destinationBufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| m_bufferSize, // VkDeviceSize size; |
| VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| m_destination = createBuffer(vk, vkDevice, &destinationBufferParams); |
| m_destinationBufferAlloc = allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *m_destination, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset())); |
| } |
| } |
| |
| tcu::TestStatus CopyImageToBuffer::iterate (void) |
| { |
| m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat, |
| m_params.src.image.extent.width, |
| m_params.src.image.extent.height, |
| m_params.src.image.extent.depth)); |
| generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.src.image.extent.depth); |
| m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat, (int)m_params.dst.buffer.size, 1)); |
| generateBuffer(m_destinationTextureLevel->getAccess(), (int)m_params.dst.buffer.size, 1, 1); |
| |
| generateExpectedResult(); |
| |
| uploadImage(m_sourceTextureLevel->getAccess(), *m_source, m_params.src.image); |
| uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc); |
| |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| // Barriers for copying image to buffer |
| const VkImageMemoryBarrier imageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *m_source, // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(m_textureFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.src.image) // deUint32 arraySize; |
| } |
| }; |
| |
| const VkBufferMemoryBarrier bufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *m_destination, // VkBuffer buffer; |
| 0u, // VkDeviceSize offset; |
| m_bufferSize // VkDeviceSize size; |
| }; |
| |
| // Copy from image to buffer |
| std::vector<VkBufferImageCopy> bufferImageCopies; |
| std::vector<VkBufferImageCopy2KHR> bufferImageCopies2KHR; |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| bufferImageCopies.push_back(m_params.regions[i].bufferImageCopy); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| bufferImageCopies2KHR.push_back(convertvkBufferImageCopyTovkBufferImageCopy2KHR(m_params.regions[i].bufferImageCopy)); |
| } |
| } |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdCopyImageToBuffer(*m_cmdBuffer, m_source.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_destination.get(), (deUint32)m_params.regions.size(), &bufferImageCopies[0]); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkCopyImageToBufferInfo2KHR copyImageToBufferInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_source.get(), // VkImage srcImage; |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout srcImageLayout; |
| m_destination.get(), // VkBuffer dstBuffer; |
| (deUint32)m_params.regions.size(), // uint32_t regionCount; |
| &bufferImageCopies2KHR[0] // const VkBufferImageCopy2KHR* pRegions; |
| }; |
| |
| vk.cmdCopyImageToBuffer2(*m_cmdBuffer, ©ImageToBufferInfo2KHR); |
| } |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| |
| submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer); |
| |
| // Read buffer data |
| de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(m_textureFormat, (int)m_params.dst.buffer.size, 1)); |
| invalidateAlloc(vk, vkDevice, *m_destinationBufferAlloc); |
| tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr())); |
| |
| return checkTestResult(resultLevel->getAccess()); |
| } |
| |
| class CopyImageToBufferTestCase : public vkt::TestCase |
| { |
| public: |
| CopyImageToBufferTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams params) |
| : vkt::TestCase (testCtx, name, description) |
| , m_params (params) |
| {} |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new CopyImageToBuffer(context, m_params); |
| } |
| |
| virtual void checkSupport (Context& context) const |
| { |
| if ((m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2) && |
| (!context.isDeviceFunctionalitySupported("VK_KHR_copy_commands2"))) |
| { |
| TCU_THROW(NotSupportedError, "VK_KHR_copy_commands2 is not supported"); |
| } |
| } |
| |
| private: |
| TestParams m_params; |
| }; |
| |
| void CopyImageToBuffer::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel) |
| { |
| DE_UNREF(mipLevel); |
| |
| deUint32 rowLength = region.bufferImageCopy.bufferRowLength; |
| if (!rowLength) |
| rowLength = region.bufferImageCopy.imageExtent.width; |
| |
| deUint32 imageHeight = region.bufferImageCopy.bufferImageHeight; |
| if (!imageHeight) |
| imageHeight = region.bufferImageCopy.imageExtent.height; |
| |
| const int texelSize = src.getFormat().getPixelSize(); |
| const VkExtent3D extent = region.bufferImageCopy.imageExtent; |
| const VkOffset3D srcOffset = region.bufferImageCopy.imageOffset; |
| const int texelOffset = (int) region.bufferImageCopy.bufferOffset / texelSize; |
| const deUint32 baseArrayLayer = region.bufferImageCopy.imageSubresource.baseArrayLayer; |
| |
| for (deUint32 z = 0; z < extent.depth; z++) |
| { |
| for (deUint32 y = 0; y < extent.height; y++) |
| { |
| int texelIndex = texelOffset + (z * imageHeight + y) * rowLength; |
| const tcu::ConstPixelBufferAccess srcSubRegion = tcu::getSubregion(src, srcOffset.x, srcOffset.y + y, srcOffset.z + z + baseArrayLayer, |
| region.bufferImageCopy.imageExtent.width, 1, 1); |
| const tcu::PixelBufferAccess dstSubRegion = tcu::getSubregion(dst, texelIndex, 0, region.bufferImageCopy.imageExtent.width, 1); |
| tcu::copy(dstSubRegion, srcSubRegion); |
| } |
| } |
| } |
| |
| // Copy from buffer to image. |
| |
| class CopyBufferToImage : public CopiesAndBlittingTestInstance |
| { |
| public: |
| CopyBufferToImage (Context& context, |
| TestParams testParams); |
| virtual tcu::TestStatus iterate (void); |
| |
| private: |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel = 0u); |
| |
| tcu::TextureFormat m_textureFormat; |
| VkDeviceSize m_bufferSize; |
| |
| Move<VkBuffer> m_source; |
| de::MovePtr<Allocation> m_sourceBufferAlloc; |
| Move<VkImage> m_destination; |
| de::MovePtr<Allocation> m_destinationImageAlloc; |
| }; |
| |
| CopyBufferToImage::CopyBufferToImage (Context& context, TestParams testParams) |
| : CopiesAndBlittingTestInstance(context, testParams) |
| , m_textureFormat(mapVkFormat(testParams.dst.image.format)) |
| , m_bufferSize(m_params.src.buffer.size * tcu::getPixelSize(m_textureFormat)) |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = context.getPhysicalDevice(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = context.getDefaultAllocator(); |
| |
| // Create source buffer |
| { |
| const VkBufferCreateInfo sourceBufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| m_bufferSize, // VkDeviceSize size; |
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| m_source = createBuffer(vk, vkDevice, &sourceBufferParams); |
| m_sourceBufferAlloc = allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *m_source, m_sourceBufferAlloc->getMemory(), m_sourceBufferAlloc->getOffset())); |
| } |
| |
| // Create destination image |
| { |
| const VkImageCreateInfo destinationImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.dst.image), // VkImageCreateFlags flags; |
| m_params.dst.image.imageType, // VkImageType imageType; |
| m_params.dst.image.format, // VkFormat format; |
| getExtent3D(m_params.dst.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.dst.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_destination = createImage(vk, vkDevice, &destinationImageParams); |
| m_destinationImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset())); |
| } |
| } |
| |
| tcu::TestStatus CopyBufferToImage::iterate (void) |
| { |
| m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat, (int)m_params.src.buffer.size, 1)); |
| generateBuffer(m_sourceTextureLevel->getAccess(), (int)m_params.src.buffer.size, 1, 1); |
| m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat, |
| m_params.dst.image.extent.width, |
| m_params.dst.image.extent.height, |
| m_params.dst.image.extent.depth)); |
| |
| generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth); |
| |
| generateExpectedResult(); |
| |
| uploadBuffer(m_sourceTextureLevel->getAccess(), *m_sourceBufferAlloc); |
| uploadImage(m_destinationTextureLevel->getAccess(), *m_destination, m_params.dst.image); |
| |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| const VkImageMemoryBarrier imageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *m_destination, // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(m_textureFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.dst.image) // deUint32 arraySize; |
| } |
| }; |
| |
| // Copy from buffer to image |
| std::vector<VkBufferImageCopy> bufferImageCopies; |
| std::vector<VkBufferImageCopy2KHR> bufferImageCopies2KHR; |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| bufferImageCopies.push_back(m_params.regions[i].bufferImageCopy); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| bufferImageCopies2KHR.push_back(convertvkBufferImageCopyTovkBufferImageCopy2KHR(m_params.regions[i].bufferImageCopy)); |
| } |
| } |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdCopyBufferToImage(*m_cmdBuffer, m_source.get(), m_destination.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)m_params.regions.size(), bufferImageCopies.data()); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkCopyBufferToImageInfo2KHR copyBufferToImageInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_source.get(), // VkBuffer srcBuffer; |
| m_destination.get(), // VkImage dstImage; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout dstImageLayout; |
| (deUint32)m_params.regions.size(), // uint32_t regionCount; |
| bufferImageCopies2KHR.data() // const VkBufferImageCopy2KHR* pRegions; |
| }; |
| |
| vk.cmdCopyBufferToImage2(*m_cmdBuffer, ©BufferToImageInfo2KHR); |
| } |
| |
| |
| endCommandBuffer(vk, *m_cmdBuffer); |
| |
| submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer); |
| |
| de::MovePtr<tcu::TextureLevel> resultLevel = readImage(*m_destination, m_params.dst.image); |
| |
| return checkTestResult(resultLevel->getAccess()); |
| } |
| |
| class CopyBufferToImageTestCase : public vkt::TestCase |
| { |
| public: |
| CopyBufferToImageTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams params) |
| : vkt::TestCase (testCtx, name, description) |
| , m_params (params) |
| {} |
| |
| virtual ~CopyBufferToImageTestCase (void) {} |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new CopyBufferToImage(context, m_params); |
| } |
| |
| virtual void checkSupport (Context& context) const |
| { |
| if ((m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2) && |
| (!context.isDeviceFunctionalitySupported("VK_KHR_copy_commands2"))) |
| { |
| TCU_THROW(NotSupportedError, "VK_KHR_copy_commands2 is not supported"); |
| } |
| } |
| |
| |
| private: |
| TestParams m_params; |
| }; |
| |
| void CopyBufferToImage::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel) |
| { |
| DE_UNREF(mipLevel); |
| |
| deUint32 rowLength = region.bufferImageCopy.bufferRowLength; |
| if (!rowLength) |
| rowLength = region.bufferImageCopy.imageExtent.width; |
| |
| deUint32 imageHeight = region.bufferImageCopy.bufferImageHeight; |
| if (!imageHeight) |
| imageHeight = region.bufferImageCopy.imageExtent.height; |
| |
| const int texelSize = dst.getFormat().getPixelSize(); |
| const VkExtent3D extent = region.bufferImageCopy.imageExtent; |
| const VkOffset3D dstOffset = region.bufferImageCopy.imageOffset; |
| const int texelOffset = (int) region.bufferImageCopy.bufferOffset / texelSize; |
| const deUint32 baseArrayLayer = region.bufferImageCopy.imageSubresource.baseArrayLayer; |
| |
| for (deUint32 z = 0; z < extent.depth; z++) |
| { |
| for (deUint32 y = 0; y < extent.height; y++) |
| { |
| int texelIndex = texelOffset + (z * imageHeight + y) * rowLength; |
| const tcu::ConstPixelBufferAccess srcSubRegion = tcu::getSubregion(src, texelIndex, 0, region.bufferImageCopy.imageExtent.width, 1); |
| const tcu::PixelBufferAccess dstSubRegion = tcu::getSubregion(dst, dstOffset.x, dstOffset.y + y, dstOffset.z + z + baseArrayLayer, |
| region.bufferImageCopy.imageExtent.width, 1, 1); |
| tcu::copy(dstSubRegion, srcSubRegion); |
| } |
| } |
| } |
| |
| class CopyBufferToDepthStencil : public CopiesAndBlittingTestInstance |
| { |
| public: |
| CopyBufferToDepthStencil (Context& context, |
| TestParams testParams); |
| virtual tcu::TestStatus iterate (void); |
| private: |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel = 0u); |
| |
| tcu::TextureFormat m_textureFormat; |
| VkDeviceSize m_bufferSize; |
| |
| Move<VkBuffer> m_source; |
| de::MovePtr<Allocation> m_sourceBufferAlloc; |
| Move<VkImage> m_destination; |
| de::MovePtr<Allocation> m_destinationImageAlloc; |
| }; |
| |
| void CopyBufferToDepthStencil::copyRegionToTextureLevel(tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel) |
| { |
| DE_UNREF(mipLevel); |
| |
| deUint32 rowLength = region.bufferImageCopy.bufferRowLength; |
| if (!rowLength) |
| rowLength = region.bufferImageCopy.imageExtent.width; |
| |
| deUint32 imageHeight = region.bufferImageCopy.bufferImageHeight; |
| if (!imageHeight) |
| imageHeight = region.bufferImageCopy.imageExtent.height; |
| |
| const int texelSize = dst.getFormat().getPixelSize(); |
| const VkExtent3D extent = region.bufferImageCopy.imageExtent; |
| const VkOffset3D dstOffset = region.bufferImageCopy.imageOffset; |
| const int texelOffset = (int)region.bufferImageCopy.bufferOffset / texelSize; |
| |
| for (deUint32 z = 0; z < extent.depth; z++) |
| { |
| for (deUint32 y = 0; y < extent.height; y++) |
| { |
| int texelIndex = texelOffset + (z * imageHeight + y) * rowLength; |
| const tcu::ConstPixelBufferAccess srcSubRegion = tcu::getSubregion(src, texelIndex, 0, region.bufferImageCopy.imageExtent.width, 1); |
| const tcu::PixelBufferAccess dstSubRegion = tcu::getSubregion(dst, dstOffset.x, dstOffset.y + y, dstOffset.z + z, |
| region.bufferImageCopy.imageExtent.width, 1, 1); |
| |
| if (region.bufferImageCopy.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) |
| { |
| tcu::copy(dstSubRegion, tcu::getEffectiveDepthStencilAccess(srcSubRegion, tcu::Sampler::MODE_DEPTH), DE_FALSE); |
| } |
| else |
| { |
| tcu::copy(dstSubRegion, tcu::getEffectiveDepthStencilAccess(srcSubRegion, tcu::Sampler::MODE_STENCIL), DE_FALSE); |
| } |
| } |
| } |
| } |
| |
| bool isSupportedDepthStencilFormat(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format) |
| { |
| VkFormatProperties formatProps; |
| vki.getPhysicalDeviceFormatProperties(physDevice, format, &formatProps); |
| return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0; |
| } |
| |
| CopyBufferToDepthStencil::CopyBufferToDepthStencil(Context& context, TestParams testParams) |
| : CopiesAndBlittingTestInstance(context, testParams) |
| , m_textureFormat(mapVkFormat(testParams.dst.image.format)) |
| , m_bufferSize(0) |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = context.getPhysicalDevice(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = context.getDefaultAllocator(); |
| const bool hasDepth = tcu::hasDepthComponent(mapVkFormat(m_params.dst.image.format).order); |
| const bool hasStencil = tcu::hasStencilComponent(mapVkFormat(m_params.dst.image.format).order); |
| |
| if (!isSupportedDepthStencilFormat(vki, vkPhysDevice, testParams.dst.image.format)) |
| { |
| TCU_THROW(NotSupportedError, "Image format not supported."); |
| } |
| |
| if (hasDepth) |
| { |
| glw::GLuint texelSize = m_textureFormat.getPixelSize(); |
| if (texelSize > sizeof(float)) |
| { |
| // We must have D32F_S8 format, depth must be packed so we only need |
| // to allocate space for the D32F part. Stencil will be separate |
| texelSize = sizeof(float); |
| } |
| m_bufferSize += static_cast<VkDeviceSize>(m_params.dst.image.extent.width) * static_cast<VkDeviceSize>(m_params.dst.image.extent.height) * static_cast<VkDeviceSize>(texelSize); |
| } |
| if (hasStencil) |
| { |
| // Stencil is always 8bits and packed. |
| m_bufferSize += static_cast<VkDeviceSize>(m_params.dst.image.extent.width) * static_cast<VkDeviceSize>(m_params.dst.image.extent.height); |
| } |
| |
| // Create source buffer, this is where the depth & stencil data will go that's used by test's regions. |
| { |
| const VkBufferCreateInfo sourceBufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| m_bufferSize, // VkDeviceSize size; |
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| m_source = createBuffer(vk, vkDevice, &sourceBufferParams); |
| m_sourceBufferAlloc = allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *m_source, m_sourceBufferAlloc->getMemory(), m_sourceBufferAlloc->getOffset())); |
| } |
| |
| // Create destination image |
| { |
| const VkImageCreateInfo destinationImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.dst.image), // VkImageCreateFlags flags; |
| m_params.dst.image.imageType, // VkImageType imageType; |
| m_params.dst.image.format, // VkFormat format; |
| getExtent3D(m_params.dst.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.dst.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_destination = createImage(vk, vkDevice, &destinationImageParams); |
| m_destinationImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset())); |
| } |
| } |
| |
| tcu::TestStatus CopyBufferToDepthStencil::iterate(void) |
| { |
| // Create source depth/stencil content. Treat as 1D texture to get different pattern |
| m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat, (int)m_params.src.buffer.size, 1)); |
| // Fill buffer with linear gradiant |
| generateBuffer(m_sourceTextureLevel->getAccess(), (int)m_params.src.buffer.size, 1, 1); |
| |
| // Create image layer for depth/stencil |
| m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat, |
| m_params.dst.image.extent.width, |
| m_params.dst.image.extent.height, |
| m_params.dst.image.extent.depth)); |
| |
| // Fill image layer with 2D gradiant |
| generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth); |
| |
| // Fill m_extendedTextureLevel with copy of m_destinationTextureLevel |
| // Then iterate over each of the regions given in m_params.regions and copy m_sourceTextureLevel content to m_extendedTextureLevel |
| // This emulates what the HW will be doing. |
| generateExpectedResult(); |
| |
| // Upload our source depth/stencil content to the source buffer |
| // This is the buffer that will be used by region commands |
| std::vector<VkBufferImageCopy> bufferImageCopies; |
| std::vector<VkBufferImageCopy2KHR> bufferImageCopies2KHR; |
| VkDeviceSize bufferOffset = 0; |
| const VkDevice vkDevice = m_context.getDevice(); |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| char* dstPtr = reinterpret_cast<char*>(m_sourceBufferAlloc->getHostPtr()); |
| bool depthLoaded = DE_FALSE; |
| bool stencilLoaded = DE_FALSE; |
| VkDeviceSize depthOffset = 0; |
| VkDeviceSize stencilOffset = 0; |
| |
| // To be able to test ordering depth & stencil differently |
| // we take the given copy regions and use that as the desired order |
| // and copy the appropriate data into place and compute the appropriate |
| // data offsets to be used in the copy command. |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| tcu::ConstPixelBufferAccess bufferAccess = m_sourceTextureLevel->getAccess(); |
| deUint32 bufferSize = bufferAccess.getWidth() * bufferAccess.getHeight() * bufferAccess.getDepth(); |
| VkBufferImageCopy copyData = m_params.regions[i].bufferImageCopy; |
| char* srcPtr; |
| |
| if (copyData.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT && !depthLoaded) |
| { |
| // Create level that is same component as depth buffer (e.g. D16, D24, D32F) |
| tcu::TextureLevel depthTexture(mapCombinedToDepthTransferFormat(bufferAccess.getFormat()), bufferAccess.getWidth(), bufferAccess.getHeight(), bufferAccess.getDepth()); |
| bufferSize *= tcu::getPixelSize(depthTexture.getFormat()); |
| // Copy depth component only from source data. This gives us packed depth-only data. |
| tcu::copy(depthTexture.getAccess(), tcu::getEffectiveDepthStencilAccess(bufferAccess, tcu::Sampler::MODE_DEPTH)); |
| srcPtr = (char*)depthTexture.getAccess().getDataPtr(); |
| // Copy packed depth-only data to output buffer |
| deMemcpy(dstPtr, srcPtr, bufferSize); |
| depthLoaded = DE_TRUE; |
| depthOffset = bufferOffset; |
| dstPtr += bufferSize; |
| bufferOffset += bufferSize; |
| copyData.bufferOffset += depthOffset; |
| } |
| else if (!stencilLoaded) |
| { |
| // Create level that is same component as stencil buffer (always 8-bits) |
| tcu::TextureLevel stencilTexture(tcu::getEffectiveDepthStencilTextureFormat(bufferAccess.getFormat(), tcu::Sampler::MODE_STENCIL), bufferAccess.getWidth(), bufferAccess.getHeight(), bufferAccess.getDepth()); |
| // Copy stencil component only from source data. This gives us packed stencil-only data. |
| tcu::copy(stencilTexture.getAccess(), tcu::getEffectiveDepthStencilAccess(bufferAccess, tcu::Sampler::MODE_STENCIL)); |
| srcPtr = (char*)stencilTexture.getAccess().getDataPtr(); |
| // Copy packed stencil-only data to output buffer |
| deMemcpy(dstPtr, srcPtr, bufferSize); |
| stencilLoaded = DE_TRUE; |
| stencilOffset = bufferOffset; |
| dstPtr += bufferSize; |
| bufferOffset += bufferSize; |
| |
| // Reference image generation uses pixel offsets based on buffer offset. |
| // We need to adjust the offset now that the stencil data is not interleaved. |
| copyData.bufferOffset /= tcu::getPixelSize(m_textureFormat); |
| |
| copyData.bufferOffset += stencilOffset; |
| } |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| bufferImageCopies.push_back(copyData); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| bufferImageCopies2KHR.push_back(convertvkBufferImageCopyTovkBufferImageCopy2KHR(copyData)); |
| } |
| } |
| |
| flushAlloc(vk, vkDevice, *m_sourceBufferAlloc); |
| |
| // Upload the depth/stencil data from m_destinationTextureLevel to initialize |
| // depth and stencil to known values. |
| // Uses uploadImageAspect so makes its own buffers for depth and stencil |
| // aspects (as needed) and copies them with independent vkCmdCopyBufferToImage commands. |
| uploadImage(m_destinationTextureLevel->getAccess(), *m_destination, m_params.dst.image); |
| |
| const VkImageMemoryBarrier imageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *m_destination, // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(m_textureFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| 1u // deUint32 arraySize; |
| } |
| }; |
| |
| // Copy from buffer to depth/stencil image |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| if (m_params.singleCommand) |
| { |
| // Issue a single copy command with regions defined by the test. |
| vk.cmdCopyBufferToImage(*m_cmdBuffer, m_source.get(), m_destination.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)m_params.regions.size(), bufferImageCopies.data()); |
| } |
| else |
| { |
| // Issue a a copy command per region defined by the test. |
| for (deUint32 i = 0; i < bufferImageCopies.size(); i++) |
| { |
| vk.cmdCopyBufferToImage(*m_cmdBuffer, m_source.get(), m_destination.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferImageCopies[i]); |
| } |
| } |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| |
| if (m_params.singleCommand) |
| { |
| // Issue a single copy command with regions defined by the test. |
| const VkCopyBufferToImageInfo2KHR copyBufferToImageInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_source.get(), // VkBuffer srcBuffer; |
| m_destination.get(), // VkImage dstImage; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout dstImageLayout; |
| (deUint32)m_params.regions.size(), // uint32_t regionCount; |
| bufferImageCopies2KHR.data() // const VkBufferImageCopy2KHR* pRegions; |
| }; |
| vk.cmdCopyBufferToImage2(*m_cmdBuffer, ©BufferToImageInfo2KHR); |
| } |
| else |
| { |
| // Issue a a copy command per region defined by the test. |
| for (deUint32 i = 0; i < bufferImageCopies2KHR.size(); i++) |
| { |
| const VkCopyBufferToImageInfo2KHR copyBufferToImageInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_source.get(), // VkBuffer srcBuffer; |
| m_destination.get(), // VkImage dstImage; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout dstImageLayout; |
| 1, // uint32_t regionCount; |
| &bufferImageCopies2KHR[i] // const VkBufferImageCopy2KHR* pRegions; |
| }; |
| // Issue a single copy command with regions defined by the test. |
| vk.cmdCopyBufferToImage2(*m_cmdBuffer, ©BufferToImageInfo2KHR); |
| } |
| } |
| } |
| endCommandBuffer(vk, *m_cmdBuffer); |
| |
| submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer); |
| |
| de::MovePtr<tcu::TextureLevel> resultLevel = readImage(*m_destination, m_params.dst.image); |
| |
| // For combined depth/stencil formats both aspects are checked even when the test only |
| // copies one. Clear such aspects here for both the result and the reference. |
| if (tcu::hasDepthComponent(m_textureFormat.order) && !depthLoaded) |
| { |
| tcu::clearDepth(m_expectedTextureLevel[0]->getAccess(), 0.0f); |
| tcu::clearDepth(resultLevel->getAccess(), 0.0f); |
| } |
| if (tcu::hasStencilComponent(m_textureFormat.order) && !stencilLoaded) |
| { |
| tcu::clearStencil(m_expectedTextureLevel[0]->getAccess(), 0); |
| tcu::clearStencil(resultLevel->getAccess(), 0); |
| } |
| |
| return checkTestResult(resultLevel->getAccess()); |
| } |
| |
| class CopyBufferToDepthStencilTestCase : public vkt::TestCase |
| { |
| public: |
| CopyBufferToDepthStencilTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams params) |
| : vkt::TestCase(testCtx, name, description) |
| , m_params(params) |
| {} |
| |
| virtual ~CopyBufferToDepthStencilTestCase (void) {} |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new CopyBufferToDepthStencil(context, m_params); |
| } |
| |
| virtual void checkSupport (Context& context) const |
| { |
| if ((m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2) && |
| (!context.isDeviceFunctionalitySupported("VK_KHR_copy_commands2"))) |
| { |
| TCU_THROW(NotSupportedError, "VK_KHR_copy_commands2 is not supported"); |
| } |
| } |
| |
| private: |
| TestParams m_params; |
| }; |
| |
| // CompressedTextureForBlit is a helper class that stores compressed texture data. |
| // Implementation is based on pipeline::TestTexture2D but it allocates only one level |
| // and has special cases needed for blits to some formats. |
| |
| class CompressedTextureForBlit |
| { |
| public: |
| CompressedTextureForBlit(const tcu::CompressedTexFormat& srcFormat, int width, int height, int depth); |
| |
| tcu::PixelBufferAccess getDecompressedAccess() const; |
| const tcu::CompressedTexture& getCompressedTexture() const; |
| |
| protected: |
| |
| tcu::CompressedTexture m_compressedTexture; |
| de::ArrayBuffer<deUint8> m_decompressedData; |
| tcu::PixelBufferAccess m_decompressedAccess; |
| }; |
| |
| CompressedTextureForBlit::CompressedTextureForBlit(const tcu::CompressedTexFormat& srcFormat, int width, int height, int depth) |
| : m_compressedTexture(srcFormat, width, height, depth) |
| { |
| de::Random random (123); |
| |
| const int compressedDataSize (m_compressedTexture.getDataSize()); |
| deUint8* compressedData ((deUint8*)m_compressedTexture.getData()); |
| |
| tcu::TextureFormat decompressedSrcFormat (tcu::getUncompressedFormat(srcFormat)); |
| const int decompressedDataSize (tcu::getPixelSize(decompressedSrcFormat) * width * height * depth); |
| |
| // generate random data for compresed textre |
| if (tcu::isAstcFormat(srcFormat)) |
| { |
| // comparison doesn't currently handle invalid blocks correctly so we use only valid blocks |
| tcu::astc::generateRandomValidBlocks(compressedData, compressedDataSize / tcu::astc::BLOCK_SIZE_BYTES, |
| srcFormat, tcu::TexDecompressionParams::ASTCMODE_LDR, random.getUint32()); |
| } |
| else if ((srcFormat == tcu::COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK) || |
| (srcFormat == tcu::COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK)) |
| { |
| // special case - when we are blitting compressed floating-point image we can't have both big and small values |
| // in compressed image; to resolve this we are constructing source texture out of set of predefined compressed |
| // blocks that after decompression will have components in proper range |
| |
| struct BC6HBlock |
| { |
| deUint32 data[4]; |
| }; |
| std::vector<BC6HBlock> validBlocks; |
| |
| if (srcFormat == tcu::COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK) |
| { |
| // define set of few valid blocks that contain values from <0; 1> range |
| validBlocks = |
| { |
| { 1686671500, 3957317723, 3010132342, 2420137890 }, |
| { 3538027716, 298848033, 1925786021, 2022072301 }, |
| { 2614043466, 1636155440, 1023731774, 1894349986 }, |
| { 3433039318, 1294346072, 1587319645, 1738449906 }, |
| { 1386298160, 1639492154, 1273285776, 361562050 }, |
| { 1310110688, 526460754, 3630858047, 537617591 }, |
| { 3270356556, 2432993217, 2415924417, 1792488857 }, |
| { 1204947583, 353249154, 3739153467, 2068076443 }, |
| }; |
| } |
| else |
| { |
| // define set of few valid blocks that contain values from <-1; 1> range |
| validBlocks = |
| { |
| { 2120678840, 3264271120, 4065378848, 3479743703 }, |
| { 1479697556, 3480872527, 3369382558, 568252340 }, |
| { 1301480032, 1607738094, 3055221704, 3663953681 }, |
| { 3531657186, 2285472028, 1429601507, 1969308187 }, |
| { 73229044, 650504649, 1120954865, 2626631975 }, |
| { 3872486086, 15326178, 2565171269, 2857722432 }, |
| { 1301480032, 1607738094, 3055221704, 3663953681 }, |
| { 73229044, 650504649, 1120954865, 2626631975 }, |
| }; |
| } |
| |
| deUint32* compressedDataUint32 = reinterpret_cast<deUint32*>(compressedData); |
| const int blocksCount = compressedDataSize / static_cast<int>(sizeof(BC6HBlock)); |
| |
| // fill data using randomly selected valid blocks |
| for (int blockNdx = 0; blockNdx < blocksCount; blockNdx++) |
| { |
| deUint32 selectedBlock = random.getUint32() % static_cast<deUint32>(validBlocks.size()); |
| deMemcpy(compressedDataUint32, validBlocks[selectedBlock].data, sizeof(BC6HBlock)); |
| compressedDataUint32 += 4; |
| } |
| } |
| else if (srcFormat != tcu::COMPRESSEDTEXFORMAT_ETC1_RGB8) |
| { |
| // random initial values cause assertion during the decompression in case of COMPRESSEDTEXFORMAT_ETC1_RGB8 format |
| for (int byteNdx = 0; byteNdx < compressedDataSize; byteNdx++) |
| compressedData[byteNdx] = 0xFF & random.getUint32(); |
| } |
| |
| // alocate space for decompressed texture |
| m_decompressedData.setStorage(decompressedDataSize); |
| m_decompressedAccess = tcu::PixelBufferAccess(decompressedSrcFormat, width, height, depth, m_decompressedData.getPtr()); |
| |
| // store decompressed data |
| m_compressedTexture.decompress(m_decompressedAccess, tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_LDR)); |
| } |
| |
| tcu::PixelBufferAccess CompressedTextureForBlit::getDecompressedAccess() const |
| { |
| return m_decompressedAccess; |
| } |
| |
| const tcu::CompressedTexture& CompressedTextureForBlit::getCompressedTexture() const |
| { |
| return m_compressedTexture; |
| } |
| |
| // Copy from image to image with scaling. |
| |
| class BlittingImages : public CopiesAndBlittingTestInstance |
| { |
| public: |
| BlittingImages (Context& context, |
| TestParams params); |
| virtual tcu::TestStatus iterate (void); |
| protected: |
| virtual tcu::TestStatus checkTestResult (tcu::ConstPixelBufferAccess result); |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, |
| tcu::PixelBufferAccess dst, |
| CopyRegion region, |
| deUint32 mipLevel = 0u); |
| virtual void generateExpectedResult (void); |
| void uploadCompressedImage (const VkImage& image, const ImageParms& parms); |
| private: |
| bool checkNonNearestFilteredResult (const tcu::ConstPixelBufferAccess& result, |
| const tcu::ConstPixelBufferAccess& clampedReference, |
| const tcu::ConstPixelBufferAccess& unclampedReference, |
| const tcu::TextureFormat& sourceFormat); |
| bool checkNearestFilteredResult (const tcu::ConstPixelBufferAccess& result, |
| const tcu::ConstPixelBufferAccess& source); |
| |
| bool checkCompressedNonNearestFilteredResult (const tcu::ConstPixelBufferAccess& result, |
| const tcu::ConstPixelBufferAccess& clampedReference, |
| const tcu::ConstPixelBufferAccess& unclampedReference, |
| const tcu::CompressedTexFormat format); |
| bool checkCompressedNearestFilteredResult (const tcu::ConstPixelBufferAccess& result, |
| const tcu::ConstPixelBufferAccess& source, |
| const tcu::CompressedTexFormat format); |
| |
| |
| Move<VkImage> m_source; |
| de::MovePtr<Allocation> m_sourceImageAlloc; |
| Move<VkImage> m_destination; |
| de::MovePtr<Allocation> m_destinationImageAlloc; |
| |
| de::MovePtr<tcu::TextureLevel> m_unclampedExpectedTextureLevel; |
| |
| // helper used only when bliting from compressed formats |
| typedef de::SharedPtr<CompressedTextureForBlit> CompressedTextureForBlitSp; |
| CompressedTextureForBlitSp m_sourceCompressedTexture; |
| CompressedTextureForBlitSp m_destinationCompressedTexture; |
| }; |
| |
| BlittingImages::BlittingImages (Context& context, TestParams params) |
| : CopiesAndBlittingTestInstance(context, params) |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = context.getPhysicalDevice(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = context.getDefaultAllocator(); |
| |
| // Create source image |
| { |
| const VkImageCreateInfo sourceImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.src.image), // VkImageCreateFlags flags; |
| m_params.src.image.imageType, // VkImageType imageType; |
| m_params.src.image.format, // VkFormat format; |
| getExtent3D(m_params.src.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.src.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| m_params.src.image.tiling, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_source = createImage(vk, vkDevice, &sourceImageParams); |
| m_sourceImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_source, m_sourceImageAlloc->getMemory(), m_sourceImageAlloc->getOffset())); |
| } |
| |
| // Create destination image |
| { |
| const VkImageCreateInfo destinationImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.dst.image), // VkImageCreateFlags flags; |
| m_params.dst.image.imageType, // VkImageType imageType; |
| m_params.dst.image.format, // VkFormat format; |
| getExtent3D(m_params.dst.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.dst.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| m_params.dst.image.tiling, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_destination = createImage(vk, vkDevice, &destinationImageParams); |
| m_destinationImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset())); |
| } |
| } |
| |
| tcu::TestStatus BlittingImages::iterate (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| const ImageParms& srcImageParams = m_params.src.image; |
| const int srcWidth = static_cast<int>(srcImageParams.extent.width); |
| const int srcHeight = static_cast<int>(srcImageParams.extent.height); |
| const int srcDepth = static_cast<int>(srcImageParams.extent.depth); |
| const ImageParms& dstImageParams = m_params.dst.image; |
| const int dstWidth = static_cast<int>(dstImageParams.extent.width); |
| const int dstHeight = static_cast<int>(dstImageParams.extent.height); |
| const int dstDepth = static_cast<int>(dstImageParams.extent.depth); |
| |
| std::vector<VkImageBlit> regions; |
| std::vector<VkImageBlit2KHR> regions2KHR; |
| |
| // setup blit regions - they are also needed for reference generation |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| regions.reserve(m_params.regions.size()); |
| for (const auto& r : m_params.regions) |
| regions.push_back(r.imageBlit); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| regions2KHR.reserve(m_params.regions.size()); |
| for (const auto& r : m_params.regions) |
| regions2KHR.push_back(convertvkImageBlitTovkImageBlit2KHR(r.imageBlit)); |
| } |
| |
| // generate source image |
| if (isCompressedFormat(srcImageParams.format)) |
| { |
| // for compressed images srcImageParams.fillMode is not used - we are using random data |
| tcu::CompressedTexFormat compressedFormat = mapVkCompressedFormat(srcImageParams.format); |
| m_sourceCompressedTexture = CompressedTextureForBlitSp(new CompressedTextureForBlit(compressedFormat, srcWidth, srcHeight, srcDepth)); |
| uploadCompressedImage(m_source.get(), srcImageParams); |
| } |
| else |
| { |
| // non-compressed image is filled with selected fillMode |
| const tcu::TextureFormat srcTcuFormat = mapVkFormat(srcImageParams.format); |
| m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(srcTcuFormat, srcWidth, srcHeight, srcDepth)); |
| generateBuffer(m_sourceTextureLevel->getAccess(), srcWidth, srcHeight, srcDepth, srcImageParams.fillMode); |
| uploadImage(m_sourceTextureLevel->getAccess(), m_source.get(), srcImageParams); |
| } |
| |
| // generate destination image |
| if (isCompressedFormat(dstImageParams.format)) |
| { |
| // compressed images are filled with random data |
| tcu::CompressedTexFormat compressedFormat = mapVkCompressedFormat(dstImageParams.format); |
| m_destinationCompressedTexture = CompressedTextureForBlitSp(new CompressedTextureForBlit(compressedFormat, srcWidth, srcHeight, srcDepth)); |
| uploadCompressedImage(m_destination.get(), dstImageParams); |
| } |
| else |
| { |
| // non-compressed image is filled with white background |
| const tcu::TextureFormat dstTcuFormat = mapVkFormat(dstImageParams.format); |
| m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dstTcuFormat, dstWidth, dstHeight, dstDepth)); |
| generateBuffer(m_destinationTextureLevel->getAccess(), dstWidth, dstHeight, dstDepth, dstImageParams.fillMode); |
| uploadImage(m_destinationTextureLevel->getAccess(), m_destination.get(), dstImageParams); |
| } |
| |
| generateExpectedResult(); |
| |
| // Barriers for copying images to buffer |
| const VkImageMemoryBarrier imageBarriers[] |
| { |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| srcImageParams.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_source.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(srcImageParams.format), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| 1u // deUint32 arraySize; |
| } |
| }, |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| dstImageParams.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstImageParams.format), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| 1u // deUint32 arraySize; |
| } |
| } |
| }; |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 2, imageBarriers); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdBlitImage(*m_cmdBuffer, m_source.get(), srcImageParams.operationLayout, m_destination.get(), dstImageParams.operationLayout, (deUint32)m_params.regions.size(), ®ions[0], m_params.filter); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkBlitImageInfo2KHR blitImageInfo2KHR |
| { |
| VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_source.get(), // VkImage srcImage; |
| srcImageParams.operationLayout, // VkImageLayout srcImageLayout; |
| m_destination.get(), // VkImage dstImage; |
| dstImageParams.operationLayout, // VkImageLayout dstImageLayout; |
| (deUint32)m_params.regions.size(), // uint32_t regionCount; |
| ®ions2KHR[0], // const VkImageBlit2KHR* pRegions; |
| m_params.filter, // VkFilter filter; |
| }; |
| vk.cmdBlitImage2(*m_cmdBuffer, &blitImageInfo2KHR); |
| } |
| |
| endCommandBuffer(vk, *m_cmdBuffer); |
| submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer); |
| |
| de::MovePtr<tcu::TextureLevel> resultLevel = readImage(*m_destination, dstImageParams); |
| tcu::PixelBufferAccess resultAccess = resultLevel->getAccess(); |
| |
| // if blit was done to a compressed format we need to decompress it to be able to verify it |
| if (m_destinationCompressedTexture) |
| { |
| deUint8* const compressedDataSrc (static_cast<deUint8*>(resultAccess.getDataPtr())); |
| const tcu::CompressedTexFormat dstCompressedFormat (mapVkCompressedFormat(dstImageParams.format)); |
| tcu::TextureLevel decompressedLevel (getUncompressedFormat(dstCompressedFormat), dstWidth, dstHeight, dstDepth); |
| tcu::PixelBufferAccess decompressedAccess (decompressedLevel.getAccess()); |
| |
| tcu::decompress(decompressedAccess, dstCompressedFormat, compressedDataSrc); |
| |
| return checkTestResult(decompressedAccess); |
| } |
| |
| return checkTestResult(resultAccess); |
| } |
| |
| static float calculateFloatConversionError (int srcBits) |
| { |
| if (srcBits > 0) |
| { |
| const int clampedBits = de::clamp<int>(srcBits, 0, 32); |
| const float srcMaxValue = de::max((float)(1ULL<<clampedBits) - 1.0f, 1.0f); |
| const float error = 1.0f / srcMaxValue; |
| |
| return de::clamp<float>(error, 0.0f, 1.0f); |
| } |
| else |
| return 1.0f; |
| } |
| |
| tcu::Vec4 getFormatThreshold (const tcu::TextureFormat& format) |
| { |
| tcu::Vec4 threshold(0.01f); |
| |
| switch (format.type) |
| { |
| case tcu::TextureFormat::HALF_FLOAT: |
| threshold = tcu::Vec4(0.005f); |
| break; |
| |
| case tcu::TextureFormat::FLOAT: |
| case tcu::TextureFormat::FLOAT64: |
| threshold = tcu::Vec4(0.001f); |
| break; |
| |
| case tcu::TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: |
| threshold = tcu::Vec4(0.02f, 0.02f, 0.0625f, 1.0f); |
| break; |
| |
| case tcu::TextureFormat::UNSIGNED_INT_999_E5_REV: |
| threshold = tcu::Vec4(0.05f, 0.05f, 0.05f, 1.0f); |
| break; |
| |
| case tcu::TextureFormat::UNORM_INT_1010102_REV: |
| threshold = tcu::Vec4(0.002f, 0.002f, 0.002f, 0.3f); |
| break; |
| |
| case tcu:: TextureFormat::UNORM_INT8: |
| threshold = tcu::Vec4(0.008f, 0.008f, 0.008f, 0.008f); |
| break; |
| |
| default: |
| const tcu::IVec4 bits = tcu::getTextureFormatMantissaBitDepth(format); |
| threshold = tcu::Vec4(calculateFloatConversionError(bits.x()), |
| calculateFloatConversionError(bits.y()), |
| calculateFloatConversionError(bits.z()), |
| calculateFloatConversionError(bits.w())); |
| } |
| |
| // Return value matching the channel order specified by the format |
| if (format.order == tcu::TextureFormat::BGR || format.order == tcu::TextureFormat::BGRA) |
| return threshold.swizzle(2, 1, 0, 3); |
| else |
| return threshold; |
| } |
| |
| tcu::Vec4 getCompressedFormatThreshold(const tcu::CompressedTexFormat& format) |
| { |
| bool isSigned(false); |
| tcu::IVec4 bitDepth(0); |
| |
| switch (format) |
| { |
| case tcu::COMPRESSEDTEXFORMAT_EAC_SIGNED_R11: |
| bitDepth = { 7, 0, 0, 0 }; |
| isSigned = true; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_EAC_R11: |
| bitDepth = { 8, 0, 0, 0 }; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11: |
| bitDepth = { 7, 7, 0, 0 }; |
| isSigned = true; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_EAC_RG11: |
| bitDepth = { 8, 8, 0, 0 }; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_ETC1_RGB8: |
| case tcu::COMPRESSEDTEXFORMAT_ETC2_RGB8: |
| case tcu::COMPRESSEDTEXFORMAT_ETC2_SRGB8: |
| bitDepth = { 8, 8, 8, 0 }; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: |
| case tcu::COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: |
| bitDepth = { 8, 8, 8, 1 }; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8: |
| case tcu::COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8: |
| case tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8: |
| bitDepth = { 8, 8, 8, 8 }; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_BC1_RGB_UNORM_BLOCK: |
| case tcu::COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK: |
| case tcu::COMPRESSEDTEXFORMAT_BC2_UNORM_BLOCK: |
| case tcu::COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK: |
| case tcu::COMPRESSEDTEXFORMAT_BC3_UNORM_BLOCK: |
| case tcu::COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK: |
| bitDepth = { 5, 6, 5, 0 }; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_BC1_RGBA_UNORM_BLOCK: |
| case tcu::COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK: |
| case tcu::COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK: |
| case tcu::COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK: |
| bitDepth = { 5, 5, 5, 1 }; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK: |
| bitDepth = { 7, 0, 0, 0 }; |
| isSigned = true; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK: |
| bitDepth = { 8, 0, 0, 0 }; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK: |
| bitDepth = { 7, 7, 0, 0 }; |
| isSigned = true; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK: |
| bitDepth = { 8, 8, 0, 0 }; |
| break; |
| |
| case tcu::COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK: |
| return tcu::Vec4(0.01f); |
| case tcu::COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK: |
| return tcu::Vec4(0.005f); |
| |
| default: |
| DE_ASSERT(DE_FALSE); |
| } |
| |
| const float range = isSigned ? 1.0f - (-1.0f) |
| : 1.0f - 0.0f; |
| tcu::Vec4 v; |
| for (int i = 0; i < 4; ++i) |
| { |
| if (bitDepth[i] == 0) |
| v[i] = 1.0f; |
| else |
| v[i] = range / static_cast<float>((1 << bitDepth[i]) - 1); |
| } |
| return v; |
| } |
| |
| bool BlittingImages::checkNonNearestFilteredResult (const tcu::ConstPixelBufferAccess& result, |
| const tcu::ConstPixelBufferAccess& clampedExpected, |
| const tcu::ConstPixelBufferAccess& unclampedExpected, |
| const tcu::TextureFormat& srcFormat) |
| { |
| tcu::TestLog& log (m_context.getTestContext().getLog()); |
| const tcu::TextureFormat dstFormat = result.getFormat(); |
| const tcu::TextureChannelClass dstChannelClass = tcu::getTextureChannelClass(dstFormat.type); |
| const tcu::TextureChannelClass srcChannelClass = tcu::getTextureChannelClass(srcFormat.type); |
| bool isOk = false; |
| |
| log << tcu::TestLog::Section("ClampedSourceImage", "Region with clamped edges on source image."); |
| |
| // if either of srcImage or dstImage stores values as a signed/unsigned integer, |
| // the other must also store values a signed/unsigned integer |
| // e.g. blit unorm to uscaled is not allowed as uscaled formats store data as integers |
| // despite the fact that both formats are sampled as floats |
| bool dstImageIsIntClass = dstChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || |
| dstChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER; |
| bool srcImageIsIntClass = srcChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || |
| srcChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER; |
| if (dstImageIsIntClass != srcImageIsIntClass) |
| { |
| log << tcu::TestLog::EndSection; |
| return false; |
| } |
| |
| if (isFloatFormat(dstFormat)) |
| { |
| const bool srcIsSRGB = tcu::isSRGB(srcFormat); |
| const tcu::Vec4 srcMaxDiff = getFormatThreshold(srcFormat) * tcu::Vec4(srcIsSRGB ? 2.0f : 1.0f); |
| const tcu::Vec4 dstMaxDiff = getFormatThreshold(dstFormat); |
| const tcu::Vec4 threshold = ( srcMaxDiff + dstMaxDiff ) * ((m_params.filter == VK_FILTER_CUBIC_EXT) ? 1.5f : 1.0f); |
| |
| isOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", clampedExpected, result, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| |
| if (!isOk) |
| { |
| log << tcu::TestLog::Section("NonClampedSourceImage", "Region with non-clamped edges on source image."); |
| isOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", unclampedExpected, result, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| } |
| } |
| else |
| { |
| tcu::UVec4 threshold; |
| // Calculate threshold depending on channel width of destination format. |
| const tcu::IVec4 dstBitDepth = tcu::getTextureFormatBitDepth(dstFormat); |
| const tcu::IVec4 srcBitDepth = tcu::getTextureFormatBitDepth(srcFormat); |
| for (deUint32 i = 0; i < 4; ++i) |
| threshold[i] = 1 + de::max( ( ( 1 << dstBitDepth[i] ) - 1 ) / de::clamp((1 << srcBitDepth[i]) - 1, 1, 256), 1); |
| |
| isOk = tcu::intThresholdCompare(log, "Compare", "Result comparsion", clampedExpected, result, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| |
| if (!isOk) |
| { |
| log << tcu::TestLog::Section("NonClampedSourceImage", "Region with non-clamped edges on source image."); |
| isOk = tcu::intThresholdCompare(log, "Compare", "Result comparsion", unclampedExpected, result, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| } |
| } |
| |
| return isOk; |
| } |
| |
| bool BlittingImages::checkCompressedNonNearestFilteredResult(const tcu::ConstPixelBufferAccess& result, |
| const tcu::ConstPixelBufferAccess& clampedReference, |
| const tcu::ConstPixelBufferAccess& unclampedReference, |
| const tcu::CompressedTexFormat format) |
| { |
| tcu::TestLog& log = m_context.getTestContext().getLog(); |
| const tcu::TextureFormat dstFormat = result.getFormat(); |
| |
| // there are rare cases wher one or few pixels have slightly bigger error |
| // in one of channels this accepted error allows those casses to pass |
| const tcu::Vec4 acceptedError (0.04f); |
| |
| const tcu::Vec4 srcMaxDiff = getCompressedFormatThreshold(format); |
| const tcu::Vec4 dstMaxDiff = m_destinationCompressedTexture ? |
| getCompressedFormatThreshold(m_destinationCompressedTexture->getCompressedTexture().getFormat()) : |
| getFormatThreshold(dstFormat); |
| const tcu::Vec4 threshold = (srcMaxDiff + dstMaxDiff) * ((m_params.filter == VK_FILTER_CUBIC_EXT) ? 1.5f : 1.0f) + acceptedError; |
| |
| bool filteredResultVerification(false); |
| tcu::Vec4 filteredResultMinValue(-6e6); |
| tcu::Vec4 filteredResultMaxValue(6e6); |
| tcu::TextureLevel filteredResult; |
| tcu::TextureLevel filteredClampedReference; |
| tcu::TextureLevel filteredUnclampedReference; |
| |
| if (((format == tcu::COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK) || |
| (format == tcu::COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK))) |
| { |
| if ((dstFormat.type == tcu::TextureFormat::FLOAT) || |
| (dstFormat.type == tcu::TextureFormat::HALF_FLOAT)) |
| { |
| // for compressed formats we are using random data and for bc6h formats |
| // this will give us also large color values; when we are bliting to |
| // a format that accepts large values we can end up with large diferences |
| // betwean filtered result and reference; to avoid that we need to remove |
| // values that are to big from verification |
| filteredResultVerification = true; |
| filteredResultMinValue = tcu::Vec4(-10.0f); |
| filteredResultMaxValue = tcu::Vec4( 10.0f); |
| } |
| else if (dstFormat.type == tcu::TextureFormat::UNSIGNED_INT_11F_11F_10F_REV) |
| { |
| // we need to clamp some formats to <0;1> range as it has |
| // small precision for big numbers compared to reference |
| filteredResultVerification = true; |
| filteredResultMinValue = tcu::Vec4(0.0f); |
| filteredResultMaxValue = tcu::Vec4(1.0f); |
| } |
| // else don't use filtered verification |
| } |
| |
| if (filteredResultVerification) |
| { |
| filteredResult.setStorage(dstFormat, result.getWidth(), result.getHeight(), result.getDepth()); |
| tcu::PixelBufferAccess filteredResultAcccess(filteredResult.getAccess()); |
| |
| filteredClampedReference.setStorage(dstFormat, result.getWidth(), result.getHeight(), result.getDepth()); |
| tcu::PixelBufferAccess filteredClampedAcccess(filteredClampedReference.getAccess()); |
| |
| filteredUnclampedReference.setStorage(dstFormat, result.getWidth(), result.getHeight(), result.getDepth()); |
| tcu::PixelBufferAccess filteredUnclampedResultAcccess(filteredUnclampedReference.getAccess()); |
| |
| for (deInt32 z = 0; z < result.getDepth(); z++) |
| for (deInt32 y = 0; y < result.getHeight(); y++) |
| for (deInt32 x = 0; x < result.getWidth(); x++) |
| { |
| tcu::Vec4 resultTexel = result.getPixel(x, y, z); |
| tcu::Vec4 clampedReferenceTexel = clampedReference.getPixel(x, y, z); |
| tcu::Vec4 unclampedReferenceTexel = unclampedReference.getPixel(x, y, z); |
| |
| resultTexel = tcu::clamp(resultTexel, filteredResultMinValue, filteredResultMaxValue); |
| clampedReferenceTexel = tcu::clamp(clampedReferenceTexel, filteredResultMinValue, filteredResultMaxValue); |
| unclampedReferenceTexel = tcu::clamp(unclampedReferenceTexel, filteredResultMinValue, filteredResultMaxValue); |
| |
| filteredResultAcccess.setPixel(resultTexel, x, y, z); |
| filteredClampedAcccess.setPixel(clampedReferenceTexel, x, y, z); |
| filteredUnclampedResultAcccess.setPixel(unclampedReferenceTexel, x, y, z); |
| } |
| } |
| |
| const tcu::ConstPixelBufferAccess clampedRef = filteredResultVerification ? filteredClampedReference.getAccess() : clampedReference; |
| const tcu::ConstPixelBufferAccess res = filteredResultVerification ? filteredResult.getAccess() : result; |
| |
| log << tcu::TestLog::Section("ClampedSourceImage", "Region with clamped edges on source image."); |
| bool isOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", clampedRef, res, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| |
| if (!isOk) |
| { |
| const tcu::ConstPixelBufferAccess unclampedRef = filteredResultVerification ? filteredUnclampedReference.getAccess() : unclampedReference; |
| |
| log << tcu::TestLog::Section("NonClampedSourceImage", "Region with non-clamped edges on source image."); |
| isOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", unclampedRef, res, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| } |
| |
| return isOk; |
| } |
| |
| //! Utility to encapsulate coordinate computation and loops. |
| struct CompareEachPixelInEachRegion |
| { |
| virtual ~CompareEachPixelInEachRegion (void) {} |
| virtual bool compare (const void* pUserData, const int x, const int y, const int z, const tcu::Vec3& srcNormCoord) const = 0; |
| |
| bool forEach (const void* pUserData, |
| const std::vector<CopyRegion>& regions, |
| const int sourceWidth, |
| const int sourceHeight, |
| const int sourceDepth, |
| const tcu::PixelBufferAccess& errorMask) const |
| { |
| bool compareOk = true; |
| |
| for (std::vector<CopyRegion>::const_iterator regionIter = regions.begin(); regionIter != regions.end(); ++regionIter) |
| { |
| const VkImageBlit& blit = regionIter->imageBlit; |
| |
| const int xStart = deMin32(blit.dstOffsets[0].x, blit.dstOffsets[1].x); |
| const int yStart = deMin32(blit.dstOffsets[0].y, blit.dstOffsets[1].y); |
| const int zStart = deMin32(blit.dstOffsets[0].z, blit.dstOffsets[1].z); |
| const int xEnd = deMax32(blit.dstOffsets[0].x, blit.dstOffsets[1].x); |
| const int yEnd = deMax32(blit.dstOffsets[0].y, blit.dstOffsets[1].y); |
| const int zEnd = deMax32(blit.dstOffsets[0].z, blit.dstOffsets[1].z); |
| const float xScale = static_cast<float>(blit.srcOffsets[1].x - blit.srcOffsets[0].x) / static_cast<float>(blit.dstOffsets[1].x - blit.dstOffsets[0].x); |
| const float yScale = static_cast<float>(blit.srcOffsets[1].y - blit.srcOffsets[0].y) / static_cast<float>(blit.dstOffsets[1].y - blit.dstOffsets[0].y); |
| const float zScale = static_cast<float>(blit.srcOffsets[1].z - blit.srcOffsets[0].z) / static_cast<float>(blit.dstOffsets[1].z - blit.dstOffsets[0].z); |
| const float srcInvW = 1.0f / static_cast<float>(sourceWidth); |
| const float srcInvH = 1.0f / static_cast<float>(sourceHeight); |
| const float srcInvD = 1.0f / static_cast<float>(sourceDepth); |
| |
| for (int z = zStart; z < zEnd; z++) |
| for (int y = yStart; y < yEnd; y++) |
| for (int x = xStart; x < xEnd; x++) |
| { |
| const tcu::Vec3 srcNormCoord |
| ( |
| (xScale * (static_cast<float>(x - blit.dstOffsets[0].x) + 0.5f) + static_cast<float>(blit.srcOffsets[0].x)) * srcInvW, |
| (yScale * (static_cast<float>(y - blit.dstOffsets[0].y) + 0.5f) + static_cast<float>(blit.srcOffsets[0].y)) * srcInvH, |
| (zScale * (static_cast<float>(z - blit.dstOffsets[0].z) + 0.5f) + static_cast<float>(blit.srcOffsets[0].z)) * srcInvD |
| ); |
| |
| if (!compare(pUserData, x, y, z, srcNormCoord)) |
| { |
| errorMask.setPixel(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); |
| compareOk = false; |
| } |
| } |
| } |
| return compareOk; |
| } |
| }; |
| |
| tcu::Vec4 getFloatOrFixedPointFormatThreshold (const tcu::TextureFormat& format) |
| { |
| const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type); |
| const tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(format); |
| |
| if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) |
| { |
| return getFormatThreshold(format); |
| } |
| else if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || |
| channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT) |
| { |
| const bool isSigned = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT); |
| const float range = isSigned ? 1.0f - (-1.0f) |
| : 1.0f - 0.0f; |
| |
| tcu::Vec4 v; |
| for (int i = 0; i < 4; ++i) |
| { |
| if (bitDepth[i] == 0) |
| v[i] = 1.0f; |
| else |
| v[i] = range / static_cast<float>((1 << bitDepth[i]) - 1); |
| } |
| return v; |
| } |
| else |
| { |
| DE_ASSERT(0); |
| return tcu::Vec4(); |
| } |
| } |
| |
| bool floatNearestBlitCompare (const tcu::ConstPixelBufferAccess& source, |
| const tcu::ConstPixelBufferAccess& result, |
| const tcu::Vec4& sourceThreshold, |
| const tcu::Vec4& resultThreshold, |
| const tcu::PixelBufferAccess& errorMask, |
| const std::vector<CopyRegion>& regions) |
| { |
| const tcu::Sampler sampler (tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST); |
| const tcu::IVec4 dstBitDepth (tcu::getTextureFormatBitDepth(result.getFormat())); |
| tcu::LookupPrecision precision; |
| |
| precision.colorMask = tcu::notEqual(dstBitDepth, tcu::IVec4(0)); |
| precision.colorThreshold = tcu::max(sourceThreshold, resultThreshold); |
| |
| const struct Capture |
| { |
| const tcu::ConstPixelBufferAccess& source; |
| const tcu::ConstPixelBufferAccess& result; |
| const tcu::Sampler& sampler; |
| const tcu::LookupPrecision& precision; |
| const bool isSRGB; |
| } capture = |
| { |
| source, result, sampler, precision, tcu::isSRGB(result.getFormat()) |
| }; |
| |
| const struct Loop : CompareEachPixelInEachRegion |
| { |
| Loop (void) {} |
| |
| bool compare (const void* pUserData, const int x, const int y, const int z, const tcu::Vec3& srcNormCoord) const |
| { |
| const Capture& c = *static_cast<const Capture*>(pUserData); |
| const tcu::TexLookupScaleMode lookupScaleDontCare = tcu::TEX_LOOKUP_SCALE_MINIFY; |
| tcu::Vec4 dstColor = c.result.getPixel(x, y, z); |
| |
| // TexLookupVerifier performs a conversion to linear space, so we have to as well |
| if (c.isSRGB) |
| dstColor = tcu::sRGBToLinear(dstColor); |
| |
| return tcu::isLevel3DLookupResultValid(c.source, c.sampler, lookupScaleDontCare, c.precision, srcNormCoord, dstColor); |
| } |
| } loop; |
| |
| return loop.forEach(&capture, regions, source.getWidth(), source.getHeight(), source.getDepth(), errorMask); |
| } |
| |
| bool intNearestBlitCompare (const tcu::ConstPixelBufferAccess& source, |
| const tcu::ConstPixelBufferAccess& result, |
| const tcu::PixelBufferAccess& errorMask, |
| const std::vector<CopyRegion>& regions) |
| { |
| const tcu::Sampler sampler (tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST); |
| tcu::IntLookupPrecision precision; |
| |
| { |
| const tcu::IVec4 srcBitDepth = tcu::getTextureFormatBitDepth(source.getFormat()); |
| const tcu::IVec4 dstBitDepth = tcu::getTextureFormatBitDepth(result.getFormat()); |
| |
| for (deUint32 i = 0; i < 4; ++i) { |
| precision.colorThreshold[i] = de::max(de::max(srcBitDepth[i] / 8, dstBitDepth[i] / 8), 1); |
| precision.colorMask[i] = dstBitDepth[i] != 0; |
| } |
| } |
| |
| // Prepare a source image with a matching (converted) pixel format. Ideally, we would've used a wrapper that |
| // does the conversion on the fly without wasting memory, but this approach is more straightforward. |
| tcu::TextureLevel convertedSourceTexture (result.getFormat(), source.getWidth(), source.getHeight(), source.getDepth()); |
| const tcu::PixelBufferAccess convertedSource = convertedSourceTexture.getAccess(); |
| |
| for (int z = 0; z < source.getDepth(); ++z) |
| for (int y = 0; y < source.getHeight(); ++y) |
| for (int x = 0; x < source.getWidth(); ++x) |
| convertedSource.setPixel(source.getPixelInt(x, y, z), x, y, z); // will be clamped to max. representable value |
| |
| const struct Capture |
| { |
| const tcu::ConstPixelBufferAccess& source; |
| const tcu::ConstPixelBufferAccess& result; |
| const tcu::Sampler& sampler; |
| const tcu::IntLookupPrecision& precision; |
| } capture = |
| { |
| convertedSource, result, sampler, precision |
| }; |
| |
| const struct Loop : CompareEachPixelInEachRegion |
| { |
| Loop (void) {} |
| |
| bool compare (const void* pUserData, const int x, const int y, const int z, const tcu::Vec3& srcNormCoord) const |
| { |
| const Capture& c = *static_cast<const Capture*>(pUserData); |
| const tcu::TexLookupScaleMode lookupScaleDontCare = tcu::TEX_LOOKUP_SCALE_MINIFY; |
| const tcu::IVec4 dstColor = c.result.getPixelInt(x, y, z); |
| |
| return tcu::isLevel3DLookupResultValid(c.source, c.sampler, lookupScaleDontCare, c.precision, srcNormCoord, dstColor); |
| } |
| } loop; |
| |
| return loop.forEach(&capture, regions, source.getWidth(), source.getHeight(), source.getDepth(), errorMask); |
| } |
| |
| bool BlittingImages::checkNearestFilteredResult (const tcu::ConstPixelBufferAccess& result, |
| const tcu::ConstPixelBufferAccess& source) |
| { |
| tcu::TestLog& log (m_context.getTestContext().getLog()); |
| const tcu::TextureFormat dstFormat = result.getFormat(); |
| const tcu::TextureFormat srcFormat = source.getFormat(); |
| const tcu::TextureChannelClass dstChannelClass = tcu::getTextureChannelClass(dstFormat.type); |
| const tcu::TextureChannelClass srcChannelClass = tcu::getTextureChannelClass(srcFormat.type); |
| |
| tcu::TextureLevel errorMaskStorage (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), result.getWidth(), result.getHeight(), result.getDepth()); |
| tcu::PixelBufferAccess errorMask = errorMaskStorage.getAccess(); |
| tcu::Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); |
| tcu::Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); |
| bool ok = false; |
| |
| tcu::clear(errorMask, tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0)); |
| |
| // if either of srcImage or dstImage stores values as a signed/unsigned integer, |
| // the other must also store values a signed/unsigned integer |
| // e.g. blit unorm to uscaled is not allowed as uscaled formats store data as integers |
| // despite the fact that both formats are sampled as floats |
| bool dstImageIsIntClass = dstChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || |
| dstChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER; |
| bool srcImageIsIntClass = srcChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || |
| srcChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER; |
| if (dstImageIsIntClass != srcImageIsIntClass) |
| return false; |
| |
| if (dstImageIsIntClass) |
| { |
| ok = intNearestBlitCompare(source, result, errorMask, m_params.regions); |
| } |
| else |
| { |
| const tcu::Vec4 srcMaxDiff = getFloatOrFixedPointFormatThreshold(source.getFormat()); |
| const tcu::Vec4 dstMaxDiff = getFloatOrFixedPointFormatThreshold(result.getFormat()); |
| ok = floatNearestBlitCompare(source, result, srcMaxDiff, dstMaxDiff, errorMask, m_params.regions); |
| } |
| |
| if (result.getFormat() != tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)) |
| tcu::computePixelScaleBias(result, pixelScale, pixelBias); |
| |
| if (!ok) |
| { |
| log << tcu::TestLog::ImageSet("Compare", "Result comparsion") |
| << tcu::TestLog::Image("Result", "Result", result, pixelScale, pixelBias) |
| << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask) |
| << tcu::TestLog::EndImageSet; |
| } |
| else |
| { |
| log << tcu::TestLog::ImageSet("Compare", "Result comparsion") |
| << tcu::TestLog::Image("Result", "Result", result, pixelScale, pixelBias) |
| << tcu::TestLog::EndImageSet; |
| } |
| |
| return ok; |
| } |
| |
| bool BlittingImages::checkCompressedNearestFilteredResult (const tcu::ConstPixelBufferAccess& result, |
| const tcu::ConstPixelBufferAccess& source, |
| const tcu::CompressedTexFormat format) |
| { |
| tcu::TestLog& log (m_context.getTestContext().getLog()); |
| tcu::TextureFormat errorMaskFormat (tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8); |
| tcu::TextureLevel errorMaskStorage (errorMaskFormat, result.getWidth(), result.getHeight(), result.getDepth()); |
| tcu::PixelBufferAccess errorMask (errorMaskStorage.getAccess()); |
| tcu::Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); |
| tcu::Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); |
| const tcu::TextureFormat& resultFormat (result.getFormat()); |
| VkFormat nativeResultFormat (mapTextureFormat(resultFormat)); |
| |
| // there are rare cases wher one or few pixels have slightly bigger error |
| // in one of channels this accepted error allows those casses to pass |
| const tcu::Vec4 acceptedError (0.04f); |
| const tcu::Vec4 srcMaxDiff (acceptedError + getCompressedFormatThreshold(format)); |
| const tcu::Vec4 dstMaxDiff (acceptedError + (m_destinationCompressedTexture ? |
| getCompressedFormatThreshold(m_destinationCompressedTexture->getCompressedTexture().getFormat()) : |
| getFloatOrFixedPointFormatThreshold(resultFormat))); |
| |
| tcu::TextureLevel clampedSourceLevel; |
| bool clampSource (false); |
| tcu::Vec4 clampSourceMinValue (-1.0f); |
| tcu::Vec4 clampSourceMaxValue (1.0f); |
| tcu::TextureLevel clampedResultLevel; |
| bool clampResult (false); |
| |
| tcu::clear(errorMask, tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0)); |
| |
| if (resultFormat != tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)) |
| tcu::computePixelScaleBias(result, pixelScale, pixelBias); |
| |
| log << tcu::TestLog::ImageSet("Compare", "Result comparsion") |
| << tcu::TestLog::Image("Result", "Result", result, pixelScale, pixelBias); |
| |
| // for compressed formats source buffer access is not actual compressed format |
| // but equivalent uncompressed format that is some cases needs additional |
| // modifications so that sampling it will produce valid reference |
| if ((format == tcu::COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK) || |
| (format == tcu::COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK)) |
| { |
| if (resultFormat.type == tcu::TextureFormat::UNSIGNED_INT_11F_11F_10F_REV) |
| { |
| // for compressed formats we are using random data and for some formats it |
| // can be outside of <-1;1> range - for cases where result is not a float |
| // format we need to clamp source to <-1;1> range as this will be done on |
| // the device but not in software sampler in framework |
| clampSource = true; |
| // for this format we also need to clamp the result as precision of |
| // this format is smaller then precision of calculations in framework; |
| // the biger color valus are the bigger errors can be |
| clampResult = true; |
| |
| if (format == tcu::COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK) |
| clampSourceMinValue = tcu::Vec4(0.0f); |
| } |
| else if ((resultFormat.type != tcu::TextureFormat::FLOAT) && |
| (resultFormat.type != tcu::TextureFormat::HALF_FLOAT)) |
| { |
| // clamp source for all non float formats |
| clampSource = true; |
| } |
| } |
| |
| if (isUnormFormat(nativeResultFormat) || isUfloatFormat(nativeResultFormat)) |
| { |
| // when tested compressed format is signed but the result format |
| // is unsigned we need to clamp source to <0; x> so that proper |
| // reference is calculated |
| if ((format == tcu::COMPRESSEDTEXFORMAT_EAC_SIGNED_R11) || |
| (format == tcu::COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11) || |
| (format == tcu::COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK) || |
| (format == tcu::COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK) || |
| (format == tcu::COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK)) |
| { |
| clampSource = true; |
| clampSourceMinValue = tcu::Vec4(0.0f); |
| } |
| } |
| |
| if (clampSource || clampResult) |
| { |
| if (clampSource) |
| { |
| clampedSourceLevel.setStorage(source.getFormat(), source.getWidth(), source.getHeight(), source.getDepth()); |
| tcu::PixelBufferAccess clampedSourceAcccess(clampedSourceLevel.getAccess()); |
| |
| for (deInt32 z = 0; z < source.getDepth() ; z++) |
| for (deInt32 y = 0; y < source.getHeight() ; y++) |
| for (deInt32 x = 0; x < source.getWidth() ; x++) |
| { |
| tcu::Vec4 texel = source.getPixel(x, y, z); |
| texel = tcu::clamp(texel, tcu::Vec4(clampSourceMinValue), tcu::Vec4(clampSourceMaxValue)); |
| clampedSourceAcccess.setPixel(texel, x, y, z); |
| } |
| } |
| |
| if (clampResult) |
| { |
| clampedResultLevel.setStorage(result.getFormat(), result.getWidth(), result.getHeight(), result.getDepth()); |
| tcu::PixelBufferAccess clampedResultAcccess(clampedResultLevel.getAccess()); |
| |
| for (deInt32 z = 0; z < result.getDepth() ; z++) |
| for (deInt32 y = 0; y < result.getHeight() ; y++) |
| for (deInt32 x = 0; x < result.getWidth() ; x++) |
| { |
| tcu::Vec4 texel = result.getPixel(x, y, z); |
| texel = tcu::clamp(texel, tcu::Vec4(-1.0f), tcu::Vec4(1.0f)); |
| clampedResultAcccess.setPixel(texel, x, y, z); |
| } |
| } |
| } |
| |
| const tcu::ConstPixelBufferAccess src = clampSource ? clampedSourceLevel.getAccess() : source; |
| const tcu::ConstPixelBufferAccess res = clampResult ? clampedResultLevel.getAccess() : result; |
| |
| if (floatNearestBlitCompare(src, res, srcMaxDiff, dstMaxDiff, errorMask, m_params.regions)) |
| { |
| log << tcu::TestLog::EndImageSet; |
| return true; |
| } |
| |
| log << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask) |
| << tcu::TestLog::EndImageSet; |
| return false; |
| } |
| |
| tcu::TestStatus BlittingImages::checkTestResult (tcu::ConstPixelBufferAccess result) |
| { |
| DE_ASSERT(m_params.filter == VK_FILTER_NEAREST || m_params.filter == VK_FILTER_LINEAR || m_params.filter == VK_FILTER_CUBIC_EXT); |
| const std::string failMessage("Result image is incorrect"); |
| |
| if (m_params.filter != VK_FILTER_NEAREST) |
| { |
| if (tcu::isCombinedDepthStencilType(result.getFormat().type)) |
| { |
| if (tcu::hasDepthComponent(result.getFormat().order)) |
| { |
| const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_DEPTH; |
| const tcu::ConstPixelBufferAccess depthResult = tcu::getEffectiveDepthStencilAccess(result, mode); |
| const tcu::ConstPixelBufferAccess clampedExpected = tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[0]->getAccess(), mode); |
| const tcu::ConstPixelBufferAccess unclampedExpected = tcu::getEffectiveDepthStencilAccess(m_unclampedExpectedTextureLevel->getAccess(), mode); |
| const tcu::TextureFormat sourceFormat = tcu::getEffectiveDepthStencilTextureFormat(mapVkFormat(m_params.src.image.format), mode); |
| |
| if (!checkNonNearestFilteredResult(depthResult, clampedExpected, unclampedExpected, sourceFormat)) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| |
| if (tcu::hasStencilComponent(result.getFormat().order)) |
| { |
| const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_STENCIL; |
| const tcu::ConstPixelBufferAccess stencilResult = tcu::getEffectiveDepthStencilAccess(result, mode); |
| const tcu::ConstPixelBufferAccess clampedExpected = tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[0]->getAccess(), mode); |
| const tcu::ConstPixelBufferAccess unclampedExpected = tcu::getEffectiveDepthStencilAccess(m_unclampedExpectedTextureLevel->getAccess(), mode); |
| const tcu::TextureFormat sourceFormat = tcu::getEffectiveDepthStencilTextureFormat(mapVkFormat(m_params.src.image.format), mode); |
| |
| if (!checkNonNearestFilteredResult(stencilResult, clampedExpected, unclampedExpected, sourceFormat)) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| } |
| else if (m_sourceCompressedTexture) |
| { |
| const tcu::CompressedTexture& compressedLevel = m_sourceCompressedTexture->getCompressedTexture(); |
| if (!checkCompressedNonNearestFilteredResult(result, m_expectedTextureLevel[0]->getAccess(), m_unclampedExpectedTextureLevel->getAccess(), compressedLevel.getFormat())) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| else |
| { |
| const tcu::TextureFormat sourceFormat = mapVkFormat(m_params.src.image.format); |
| if (!checkNonNearestFilteredResult(result, m_expectedTextureLevel[0]->getAccess(), m_unclampedExpectedTextureLevel->getAccess(), sourceFormat)) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| } |
| else // NEAREST filtering |
| { |
| if (tcu::isCombinedDepthStencilType(result.getFormat().type)) |
| { |
| if (tcu::hasDepthComponent(result.getFormat().order)) |
| { |
| const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_DEPTH; |
| const tcu::ConstPixelBufferAccess depthResult = tcu::getEffectiveDepthStencilAccess(result, mode); |
| const tcu::ConstPixelBufferAccess depthSource = tcu::getEffectiveDepthStencilAccess(m_sourceTextureLevel->getAccess(), mode); |
| |
| if (!checkNearestFilteredResult(depthResult, depthSource)) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| |
| if (tcu::hasStencilComponent(result.getFormat().order)) |
| { |
| const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_STENCIL; |
| const tcu::ConstPixelBufferAccess stencilResult = tcu::getEffectiveDepthStencilAccess(result, mode); |
| const tcu::ConstPixelBufferAccess stencilSource = tcu::getEffectiveDepthStencilAccess(m_sourceTextureLevel->getAccess(), mode); |
| |
| if (!checkNearestFilteredResult(stencilResult, stencilSource)) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| } |
| else if (m_sourceCompressedTexture) |
| { |
| const tcu::CompressedTexture& compressedLevel = m_sourceCompressedTexture->getCompressedTexture(); |
| const tcu::PixelBufferAccess& decompressedLevel = m_sourceCompressedTexture->getDecompressedAccess(); |
| |
| if (!checkCompressedNearestFilteredResult(result, decompressedLevel, compressedLevel.getFormat())) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| else if (!checkNearestFilteredResult(result, m_sourceTextureLevel->getAccess())) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| tcu::Vec4 linearToSRGBIfNeeded (const tcu::TextureFormat& format, const tcu::Vec4& color) |
| { |
| return isSRGB(format) ? linearToSRGB(color) : color; |
| } |
| |
| void scaleFromWholeSrcBuffer (const tcu::PixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const VkOffset3D regionOffset, const VkOffset3D regionExtent, tcu::Sampler::FilterMode filter, const MirrorMode mirrorMode = 0u) |
| { |
| DE_ASSERT(filter == tcu::Sampler::LINEAR || filter == tcu::Sampler::CUBIC); |
| |
| tcu::Sampler sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, |
| filter, filter, 0.0f, false); |
| |
| float sX = (float)regionExtent.x / (float)dst.getWidth(); |
| float sY = (float)regionExtent.y / (float)dst.getHeight(); |
| float sZ = (float)regionExtent.z / (float)dst.getDepth(); |
| |
| for (int z = 0; z < dst.getDepth(); z++) |
| for (int y = 0; y < dst.getHeight(); y++) |
| for (int x = 0; x < dst.getWidth(); x++) |
| { |
| float srcX = ((mirrorMode & MIRROR_MODE_X) != 0) ? (float)regionExtent.x + (float)regionOffset.x - ((float)x+0.5f)*sX : (float)regionOffset.x + ((float)x+0.5f)*sX; |
| float srcY = ((mirrorMode & MIRROR_MODE_Y) != 0) ? (float)regionExtent.y + (float)regionOffset.y - ((float)y+0.5f)*sY : (float)regionOffset.y + ((float)y+0.5f)*sY; |
| float srcZ = ((mirrorMode & MIRROR_MODE_Z) != 0) ? (float)regionExtent.z + (float)regionOffset.z - ((float)z+0.5f)*sZ : (float)regionOffset.z + ((float)z+0.5f)*sZ; |
| if (dst.getDepth() > 1) |
| dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample3D(sampler, filter, srcX, srcY, srcZ)), x, y, z); |
| else |
| dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample2D(sampler, filter, srcX, srcY, 0)), x, y); |
| } |
| } |
| |
| void blit (const tcu::PixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::Sampler::FilterMode filter, const MirrorMode mirrorMode) |
| { |
| DE_ASSERT(filter == tcu::Sampler::NEAREST || filter == tcu::Sampler::LINEAR || filter == tcu::Sampler::CUBIC); |
| |
| tcu::Sampler sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, |
| filter, filter, 0.0f, false); |
| |
| const float sX = (float)src.getWidth() / (float)dst.getWidth(); |
| const float sY = (float)src.getHeight() / (float)dst.getHeight(); |
| const float sZ = (float)src.getDepth() / (float)dst.getDepth(); |
| |
| const int xOffset = (mirrorMode & MIRROR_MODE_X) ? dst.getWidth() - 1 : 0; |
| const int yOffset = (mirrorMode & MIRROR_MODE_Y) ? dst.getHeight() - 1 : 0; |
| const int zOffset = (mirrorMode & MIRROR_MODE_Z) ? dst.getDepth() - 1 : 0; |
| |
| const int xScale = (mirrorMode & MIRROR_MODE_X) ? -1 : 1; |
| const int yScale = (mirrorMode & MIRROR_MODE_Y) ? -1 : 1; |
| const int zScale = (mirrorMode & MIRROR_MODE_Z) ? -1 : 1; |
| |
| for (int z = 0; z < dst.getDepth(); ++z) |
| for (int y = 0; y < dst.getHeight(); ++y) |
| for (int x = 0; x < dst.getWidth(); ++x) |
| { |
| dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample3D(sampler, filter, ((float)x + 0.5f) * sX, ((float)y + 0.5f) * sY, ((float)z + 0.5f) * sZ)), x * xScale + xOffset, y * yScale + yOffset, z * zScale + zOffset); |
| } |
| } |
| |
| void flipCoordinates (CopyRegion& region, const MirrorMode mirrorMode) |
| { |
| const VkOffset3D dstOffset0 = region.imageBlit.dstOffsets[0]; |
| const VkOffset3D dstOffset1 = region.imageBlit.dstOffsets[1]; |
| const VkOffset3D srcOffset0 = region.imageBlit.srcOffsets[0]; |
| const VkOffset3D srcOffset1 = region.imageBlit.srcOffsets[1]; |
| |
| if (mirrorMode != 0u) |
| { |
| //sourceRegion |
| region.imageBlit.srcOffsets[0].x = std::min(srcOffset0.x, srcOffset1.x); |
| region.imageBlit.srcOffsets[0].y = std::min(srcOffset0.y, srcOffset1.y); |
| region.imageBlit.srcOffsets[0].z = std::min(srcOffset0.z, srcOffset1.z); |
| |
| region.imageBlit.srcOffsets[1].x = std::max(srcOffset0.x, srcOffset1.x); |
| region.imageBlit.srcOffsets[1].y = std::max(srcOffset0.y, srcOffset1.y); |
| region.imageBlit.srcOffsets[1].z = std::max(srcOffset0.z, srcOffset1.z); |
| |
| //destinationRegion |
| region.imageBlit.dstOffsets[0].x = std::min(dstOffset0.x, dstOffset1.x); |
| region.imageBlit.dstOffsets[0].y = std::min(dstOffset0.y, dstOffset1.y); |
| region.imageBlit.dstOffsets[0].z = std::min(dstOffset0.z, dstOffset1.z); |
| |
| region.imageBlit.dstOffsets[1].x = std::max(dstOffset0.x, dstOffset1.x); |
| region.imageBlit.dstOffsets[1].y = std::max(dstOffset0.y, dstOffset1.y); |
| region.imageBlit.dstOffsets[1].z = std::max(dstOffset0.z, dstOffset1.z); |
| } |
| } |
| |
| // Mirror X, Y and Z as required by the offset values in the 3 axes. |
| MirrorMode getMirrorMode(const VkOffset3D from, const VkOffset3D to) |
| { |
| MirrorMode mode = 0u; |
| |
| if (from.x > to.x) |
| mode |= MIRROR_MODE_X; |
| |
| if (from.y > to.y) |
| mode |= MIRROR_MODE_Y; |
| |
| if (from.z > to.z) |
| mode |= MIRROR_MODE_Z; |
| |
| return mode; |
| } |
| |
| // Mirror the axes that are mirrored either in the source or destination, but not both. |
| MirrorMode getMirrorMode(const VkOffset3D s1, const VkOffset3D s2, const VkOffset3D d1, const VkOffset3D d2) |
| { |
| static const MirrorModeBits kBits[] = { MIRROR_MODE_X, MIRROR_MODE_Y, MIRROR_MODE_Z }; |
| |
| const MirrorMode source = getMirrorMode(s1, s2); |
| const MirrorMode destination = getMirrorMode(d1, d2); |
| |
| MirrorMode mode = 0u; |
| |
| for (int i = 0; i < DE_LENGTH_OF_ARRAY(kBits); ++i) |
| { |
| const MirrorModeBits bit = kBits[i]; |
| if ((source & bit) != (destination & bit)) |
| mode |= bit; |
| } |
| |
| return mode; |
| } |
| |
| void BlittingImages::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel) |
| { |
| DE_UNREF(mipLevel); |
| |
| const MirrorMode mirrorMode = getMirrorMode(region.imageBlit.srcOffsets[0], |
| region.imageBlit.srcOffsets[1], |
| region.imageBlit.dstOffsets[0], |
| region.imageBlit.dstOffsets[1]); |
| |
| flipCoordinates(region, mirrorMode); |
| |
| const VkOffset3D srcOffset = region.imageBlit.srcOffsets[0]; |
| const VkOffset3D srcExtent = |
| { |
| region.imageBlit.srcOffsets[1].x - srcOffset.x, |
| region.imageBlit.srcOffsets[1].y - srcOffset.y, |
| region.imageBlit.srcOffsets[1].z - srcOffset.z, |
| }; |
| const VkOffset3D dstOffset = region.imageBlit.dstOffsets[0]; |
| const VkOffset3D dstExtent = |
| { |
| region.imageBlit.dstOffsets[1].x - dstOffset.x, |
| region.imageBlit.dstOffsets[1].y - dstOffset.y, |
| region.imageBlit.dstOffsets[1].z - dstOffset.z, |
| }; |
| |
| tcu::Sampler::FilterMode filter; |
| switch (m_params.filter) |
| { |
| case VK_FILTER_LINEAR: filter = tcu::Sampler::LINEAR; break; |
| case VK_FILTER_CUBIC_EXT: filter = tcu::Sampler::CUBIC; break; |
| case VK_FILTER_NEAREST: |
| default: filter = tcu::Sampler::NEAREST; break; |
| } |
| |
| if (tcu::isCombinedDepthStencilType(src.getFormat().type)) |
| { |
| DE_ASSERT(src.getFormat() == dst.getFormat()); |
| |
| // Scale depth. |
| if (tcu::hasDepthComponent(src.getFormat().order)) |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, srcExtent.x, srcExtent.y, srcExtent.z), tcu::Sampler::MODE_DEPTH); |
| const tcu::PixelBufferAccess dstSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstOffset.z, dstExtent.x, dstExtent.y, dstExtent.z), tcu::Sampler::MODE_DEPTH); |
| tcu::scale(dstSubRegion, srcSubRegion, filter); |
| |
| if (filter != tcu::Sampler::NEAREST) |
| { |
| const tcu::ConstPixelBufferAccess depthSrc = getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_DEPTH); |
| const tcu::PixelBufferAccess unclampedSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(m_unclampedExpectedTextureLevel->getAccess(), dstOffset.x, dstOffset.y, dstOffset.z, dstExtent.x, dstExtent.y, dstExtent.z), tcu::Sampler::MODE_DEPTH); |
| scaleFromWholeSrcBuffer(unclampedSubRegion, depthSrc, srcOffset, srcExtent, filter, mirrorMode); |
| } |
| } |
| |
| // Scale stencil. |
| if (tcu::hasStencilComponent(src.getFormat().order)) |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, srcExtent.x, srcExtent.y, srcExtent.z), tcu::Sampler::MODE_STENCIL); |
| const tcu::PixelBufferAccess dstSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstOffset.z, dstExtent.x, dstExtent.y, dstExtent.z), tcu::Sampler::MODE_STENCIL); |
| blit(dstSubRegion, srcSubRegion, filter, mirrorMode); |
| |
| if (filter != tcu::Sampler::NEAREST) |
| { |
| const tcu::ConstPixelBufferAccess stencilSrc = getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_STENCIL); |
| const tcu::PixelBufferAccess unclampedSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(m_unclampedExpectedTextureLevel->getAccess(), dstOffset.x, dstOffset.y, dstOffset.z, dstExtent.x, dstExtent.y, dstExtent.z), tcu::Sampler::MODE_STENCIL); |
| scaleFromWholeSrcBuffer(unclampedSubRegion, stencilSrc, srcOffset, srcExtent, filter, mirrorMode); |
| } |
| } |
| } |
| else |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, srcExtent.x, srcExtent.y, srcExtent.z); |
| const tcu::PixelBufferAccess dstSubRegion = tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstOffset.z, dstExtent.x, dstExtent.y, dstExtent.z); |
| blit(dstSubRegion, srcSubRegion, filter, mirrorMode); |
| |
| if (filter != tcu::Sampler::NEAREST) |
| { |
| const tcu::PixelBufferAccess unclampedSubRegion = tcu::getSubregion(m_unclampedExpectedTextureLevel->getAccess(), dstOffset.x, dstOffset.y, dstOffset.z, dstExtent.x, dstExtent.y, dstExtent.z); |
| scaleFromWholeSrcBuffer(unclampedSubRegion, src, srcOffset, srcExtent, filter, mirrorMode); |
| } |
| } |
| } |
| |
| void BlittingImages::generateExpectedResult (void) |
| { |
| const tcu::ConstPixelBufferAccess src = m_sourceCompressedTexture ? m_sourceCompressedTexture->getDecompressedAccess() : m_sourceTextureLevel->getAccess(); |
| const tcu::ConstPixelBufferAccess dst = m_destinationCompressedTexture ? m_destinationCompressedTexture->getDecompressedAccess() : m_destinationTextureLevel->getAccess(); |
| |
| m_expectedTextureLevel[0] = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth())); |
| tcu::copy(m_expectedTextureLevel[0]->getAccess(), dst); |
| |
| if (m_params.filter != VK_FILTER_NEAREST) |
| { |
| m_unclampedExpectedTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth())); |
| tcu::copy(m_unclampedExpectedTextureLevel->getAccess(), dst); |
| } |
| |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| CopyRegion region = m_params.regions[i]; |
| copyRegionToTextureLevel(src, m_expectedTextureLevel[0]->getAccess(), region); |
| } |
| } |
| |
| void BlittingImages::uploadCompressedImage (const VkImage& image, const ImageParms& parms) |
| { |
| DE_ASSERT(m_sourceCompressedTexture); |
| |
| const InstanceInterface& vki = m_context.getInstanceInterface(); |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = m_context.getPhysicalDevice(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = m_context.getDefaultAllocator(); |
| Move<VkBuffer> buffer; |
| const deUint32 bufferSize = m_sourceCompressedTexture->getCompressedTexture().getDataSize(); |
| de::MovePtr<Allocation> bufferAlloc; |
| const deUint32 arraySize = getArraySize(parms); |
| const VkExtent3D imageExtent |
| { |
| parms.extent.width, |
| (parms.imageType != VK_IMAGE_TYPE_1D) ? parms.extent.height : 1u, |
| (parms.imageType == VK_IMAGE_TYPE_3D) ? parms.extent.depth : 1u, |
| }; |
| |
| // Create source buffer |
| { |
| const VkBufferCreateInfo bufferParams |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| bufferSize, // VkDeviceSize size; |
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| buffer = createBuffer(vk, vkDevice, &bufferParams); |
| bufferAlloc = allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *buffer, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset())); |
| } |
| |
| // Barriers for copying buffer to image |
| const VkBufferMemoryBarrier preBufferBarrier |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *buffer, // VkBuffer buffer; |
| 0u, // VkDeviceSize offset; |
| bufferSize // VkDeviceSize size; |
| }; |
| |
| const VkImageMemoryBarrier preImageBarrier |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| image, // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| arraySize, // deUint32 arraySize; |
| } |
| }; |
| |
| const VkImageMemoryBarrier postImageBarrier |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| image, // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| arraySize, // deUint32 arraySize; |
| } |
| }; |
| |
| const VkExtent3D copyExtent |
| { |
| imageExtent.width, |
| imageExtent.height, |
| imageExtent.depth |
| }; |
| |
| VkBufferImageCopy copyRegion |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| copyExtent.width, // deUint32 bufferRowLength; |
| copyExtent.height, // deUint32 bufferImageHeight; |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arraySize, // deUint32 layerCount; |
| }, // VkImageSubresourceLayers imageSubresource; |
| { 0, 0, 0 }, // VkOffset3D imageOffset; |
| copyExtent // VkExtent3D imageExtent; |
| }; |
| |
| // Write buffer data |
| deMemcpy(bufferAlloc->getHostPtr(), m_sourceCompressedTexture->getCompressedTexture().getData(), bufferSize); |
| flushAlloc(vk, vkDevice, *bufferAlloc); |
| |
| // Copy buffer to image |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, |
| 1, &preBufferBarrier, 1, &preImageBarrier); |
| vk.cmdCopyBufferToImage(*m_cmdBuffer, *buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| |
| submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer); |
| } |
| |
| |
| class BlitImageTestCase : public vkt::TestCase |
| { |
| public: |
| BlitImageTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams params) |
| : vkt::TestCase (testCtx, name, description) |
| , m_params (params) |
| {} |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new BlittingImages(context, m_params); |
| } |
| |
| virtual void checkSupport (Context& context) const |
| { |
| VkImageFormatProperties properties; |
| if (context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.src.image.format, |
| m_params.src.image.imageType, |
| m_params.src.image.tiling, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT, |
| 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) |
| { |
| TCU_THROW(NotSupportedError, "Source format not supported"); |
| } |
| if (context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.dst.image.format, |
| m_params.dst.image.imageType, |
| m_params.dst.image.tiling, |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, |
| 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) |
| { |
| TCU_THROW(NotSupportedError, "Destination format not supported"); |
| } |
| |
| VkFormatProperties srcFormatProperties; |
| context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), m_params.src.image.format, &srcFormatProperties); |
| VkFormatFeatureFlags srcFormatFeatures = m_params.src.image.tiling == VK_IMAGE_TILING_LINEAR ? srcFormatProperties.linearTilingFeatures : srcFormatProperties.optimalTilingFeatures; |
| if (!(srcFormatFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) |
| { |
| TCU_THROW(NotSupportedError, "Format feature blit source not supported"); |
| } |
| |
| VkFormatProperties dstFormatProperties; |
| context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), m_params.dst.image.format, &dstFormatProperties); |
| VkFormatFeatureFlags dstFormatFeatures = m_params.dst.image.tiling == VK_IMAGE_TILING_LINEAR ? dstFormatProperties.linearTilingFeatures : dstFormatProperties.optimalTilingFeatures; |
| if (!(dstFormatFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) |
| { |
| TCU_THROW(NotSupportedError, "Format feature blit destination not supported"); |
| } |
| |
| if (m_params.filter == VK_FILTER_LINEAR && !(srcFormatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) |
| { |
| TCU_THROW(NotSupportedError, "Source format feature sampled image filter linear not supported"); |
| } |
| |
| if (m_params.filter == VK_FILTER_CUBIC_EXT) |
| { |
| context.requireDeviceFunctionality("VK_EXT_filter_cubic"); |
| |
| if (!(srcFormatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) |
| { |
| TCU_THROW(NotSupportedError, "Source format feature sampled image filter cubic not supported"); |
| } |
| } |
| |
| if (m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_copy_commands2")) |
| { |
| TCU_THROW(NotSupportedError, "VK_KHR_copy_commands2 is not supported"); |
| } |
| } |
| } |
| |
| private: |
| TestParams m_params; |
| }; |
| |
| class BlittingMipmaps : public CopiesAndBlittingTestInstance |
| { |
| public: |
| BlittingMipmaps (Context& context, |
| TestParams params); |
| virtual tcu::TestStatus iterate (void); |
| protected: |
| virtual tcu::TestStatus checkTestResult (tcu::ConstPixelBufferAccess result = tcu::ConstPixelBufferAccess()); |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel = 0u); |
| virtual void generateExpectedResult (void); |
| private: |
| bool checkNonNearestFilteredResult (void); |
| bool checkNearestFilteredResult (void); |
| |
| Move<VkImage> m_source; |
| de::MovePtr<Allocation> m_sourceImageAlloc; |
| Move<VkImage> m_destination; |
| de::MovePtr<Allocation> m_destinationImageAlloc; |
| |
| de::MovePtr<tcu::TextureLevel> m_unclampedExpectedTextureLevel[16]; |
| }; |
| |
| BlittingMipmaps::BlittingMipmaps (Context& context, TestParams params) |
| : CopiesAndBlittingTestInstance (context, params) |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = context.getPhysicalDevice(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = context.getDefaultAllocator(); |
| |
| // Create source image |
| { |
| const VkImageCreateInfo sourceImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.src.image), // VkImageCreateFlags flags; |
| m_params.src.image.imageType, // VkImageType imageType; |
| m_params.src.image.format, // VkFormat format; |
| getExtent3D(m_params.src.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.src.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_source = createImage(vk, vkDevice, &sourceImageParams); |
| m_sourceImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_source, m_sourceImageAlloc->getMemory(), m_sourceImageAlloc->getOffset())); |
| } |
| |
| // Create destination image |
| { |
| const VkImageCreateInfo destinationImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.dst.image), // VkImageCreateFlags flags; |
| m_params.dst.image.imageType, // VkImageType imageType; |
| m_params.dst.image.format, // VkFormat format; |
| getExtent3D(m_params.dst.image), // VkExtent3D extent; |
| m_params.mipLevels, // deUint32 mipLevels; |
| getArraySize(m_params.dst.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_destination = createImage(vk, vkDevice, &destinationImageParams); |
| m_destinationImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset())); |
| } |
| } |
| |
| tcu::TestStatus BlittingMipmaps::iterate (void) |
| { |
| const tcu::TextureFormat srcTcuFormat = mapVkFormat(m_params.src.image.format); |
| const tcu::TextureFormat dstTcuFormat = mapVkFormat(m_params.dst.image.format); |
| m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(srcTcuFormat, |
| m_params.src.image.extent.width, |
| m_params.src.image.extent.height, |
| m_params.src.image.extent.depth)); |
| generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.src.image.extent.depth, m_params.src.image.fillMode); |
| m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dstTcuFormat, |
| (int)m_params.dst.image.extent.width, |
| (int)m_params.dst.image.extent.height, |
| (int)m_params.dst.image.extent.depth)); |
| generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth, m_params.dst.image.fillMode); |
| generateExpectedResult(); |
| |
| uploadImage(m_sourceTextureLevel->getAccess(), m_source.get(), m_params.src.image); |
| |
| uploadImage(m_destinationTextureLevel->getAccess(), m_destination.get(), m_params.dst.image, m_params.mipLevels); |
| |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| std::vector<VkImageBlit> regions; |
| std::vector<VkImageBlit2KHR> regions2KHR; |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| regions.push_back(m_params.regions[i].imageBlit); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| regions2KHR.push_back(convertvkImageBlitTovkImageBlit2KHR(m_params.regions[i].imageBlit)); |
| } |
| } |
| |
| // Copy source image to mip level 0 when generating mipmaps with multiple blit commands |
| if (!m_params.singleCommand) |
| uploadImage(m_sourceTextureLevel->getAccess(), m_destination.get(), m_params.dst.image, 1u); |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| |
| // Blit all mip levels with a single blit command |
| if (m_params.singleCommand) |
| { |
| { |
| // Source image layout |
| const VkImageMemoryBarrier srcImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| m_params.src.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_source.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(srcTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.src.image) // deUint32 arraySize; |
| } |
| }; |
| |
| // Destination image layout |
| const VkImageMemoryBarrier dstImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| m_params.dst.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| m_params.mipLevels, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.dst.image) // deUint32 arraySize; |
| } |
| }; |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &srcImageBarrier); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &dstImageBarrier); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdBlitImage(*m_cmdBuffer, m_source.get(), m_params.src.image.operationLayout, m_destination.get(), m_params.dst.image.operationLayout, (deUint32)m_params.regions.size(), ®ions[0], m_params.filter); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkBlitImageInfo2KHR BlitImageInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_source.get(), // VkImage srcImage; |
| m_params.src.image.operationLayout, // VkImageLayout srcImageLayout; |
| m_destination.get(), // VkImage dstImage; |
| m_params.dst.image.operationLayout, // VkImageLayout dstImageLayout; |
| (deUint32)m_params.regions.size(), // uint32_t regionCount; |
| ®ions2KHR[0], // const VkImageBlit2KHR* pRegions; |
| m_params.filter // VkFilter filter; |
| }; |
| vk.cmdBlitImage2(*m_cmdBuffer, &BlitImageInfo2KHR); |
| } |
| } |
| } |
| // Blit mip levels with multiple blit commands |
| else |
| { |
| // Prepare all mip levels for reading |
| { |
| for (deUint32 barrierno = 0; barrierno < m_params.barrierCount; barrierno++) |
| { |
| VkImageMemoryBarrier preImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| m_params.src.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| VK_REMAINING_MIP_LEVELS, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.src.image) // deUint32 arraySize; |
| } |
| }; |
| |
| if (getArraySize(m_params.src.image) == 1) |
| { |
| DE_ASSERT(barrierno < m_params.mipLevels); |
| preImageBarrier.subresourceRange.baseMipLevel = barrierno; |
| preImageBarrier.subresourceRange.levelCount = (barrierno + 1 < m_params.barrierCount) ? 1 : VK_REMAINING_MIP_LEVELS; |
| } |
| else |
| { |
| preImageBarrier.subresourceRange.baseArrayLayer = barrierno; |
| preImageBarrier.subresourceRange.layerCount = (barrierno + 1 < m_params.barrierCount) ? 1 : VK_REMAINING_ARRAY_LAYERS; |
| } |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier); |
| } |
| } |
| |
| for (deUint32 regionNdx = 0u; regionNdx < (deUint32)m_params.regions.size(); regionNdx++) |
| { |
| const deUint32 mipLevel = m_params.regions[regionNdx].imageBlit.dstSubresource.mipLevel; |
| |
| // Prepare single mip level for writing |
| const VkImageMemoryBarrier preImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| m_params.src.image.operationLayout, // VkImageLayout oldLayout; |
| m_params.dst.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstTcuFormat), // VkImageAspectFlags aspectMask; |
| mipLevel, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.dst.image) // deUint32 arraySize; |
| } |
| }; |
| |
| // Prepare single mip level for reading |
| const VkImageMemoryBarrier postImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| m_params.dst.image.operationLayout, // VkImageLayout oldLayout; |
| m_params.src.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstTcuFormat), // VkImageAspectFlags aspectMask; |
| mipLevel, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.src.image) // deUint32 arraySize; |
| } |
| }; |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdBlitImage(*m_cmdBuffer, m_destination.get(), m_params.src.image.operationLayout, m_destination.get(), m_params.dst.image.operationLayout, 1u, ®ions[regionNdx], m_params.filter); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkBlitImageInfo2KHR BlitImageInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_destination.get(), // VkImage srcImage; |
| m_params.src.image.operationLayout, // VkImageLayout srcImageLayout; |
| m_destination.get(), // VkImage dstImage; |
| m_params.dst.image.operationLayout, // VkImageLayout dstImageLayout; |
| 1u, // uint32_t regionCount; |
| ®ions2KHR[regionNdx], // const VkImageBlit2KHR* pRegions; |
| m_params.filter // VkFilter filter; |
| }; |
| vk.cmdBlitImage2(*m_cmdBuffer, &BlitImageInfo2KHR); |
| } |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier); |
| } |
| |
| // Prepare all mip levels for writing |
| { |
| const VkImageMemoryBarrier postImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| m_params.src.image.operationLayout, // VkImageLayout oldLayout; |
| m_params.dst.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| VK_REMAINING_MIP_LEVELS, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.dst.image) // deUint32 arraySize; |
| } |
| }; |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier); |
| } |
| } |
| |
| endCommandBuffer(vk, *m_cmdBuffer); |
| submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer); |
| |
| return checkTestResult(); |
| } |
| |
| bool BlittingMipmaps::checkNonNearestFilteredResult (void) |
| { |
| tcu::TestLog& log (m_context.getTestContext().getLog()); |
| bool allLevelsOk = true; |
| |
| for (deUint32 mipLevelNdx = 0u; mipLevelNdx < m_params.mipLevels; mipLevelNdx++) |
| { |
| // Update reference results with previous results that have been verified. |
| // This needs to be done such that accumulated errors don't exceed the fixed threshold. |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| const CopyRegion region = m_params.regions[i]; |
| const deUint32 srcMipLevel = m_params.regions[i].imageBlit.srcSubresource.mipLevel; |
| const deUint32 dstMipLevel = m_params.regions[i].imageBlit.dstSubresource.mipLevel; |
| de::MovePtr<tcu::TextureLevel> prevResultLevel; |
| tcu::ConstPixelBufferAccess src; |
| if (srcMipLevel < mipLevelNdx) |
| { |
| // Generate expected result from rendered result that was previously verified |
| prevResultLevel = readImage(*m_destination, m_params.dst.image, srcMipLevel); |
| src = prevResultLevel->getAccess(); |
| } |
| else |
| { |
| // Previous reference mipmaps might have changed, so recompute expected result |
| src = m_expectedTextureLevel[srcMipLevel]->getAccess(); |
| } |
| copyRegionToTextureLevel(src, m_expectedTextureLevel[dstMipLevel]->getAccess(), region, dstMipLevel); |
| } |
| |
| de::MovePtr<tcu::TextureLevel> resultLevel = readImage(*m_destination, m_params.dst.image, mipLevelNdx); |
| const tcu::ConstPixelBufferAccess& resultAccess = resultLevel->getAccess(); |
| |
| const tcu::Sampler::DepthStencilMode mode = tcu::hasDepthComponent(resultAccess.getFormat().order) ? tcu::Sampler::MODE_DEPTH : |
| tcu::hasStencilComponent(resultAccess.getFormat().order) ? tcu::Sampler::MODE_STENCIL : |
| tcu::Sampler::MODE_LAST; |
| const tcu::ConstPixelBufferAccess result = tcu::hasDepthComponent(resultAccess.getFormat().order) ? getEffectiveDepthStencilAccess(resultAccess, mode) : |
| tcu::hasStencilComponent(resultAccess.getFormat().order) ? getEffectiveDepthStencilAccess(resultAccess, mode) : |
| resultAccess; |
| const tcu::ConstPixelBufferAccess clampedLevel = tcu::hasDepthComponent(resultAccess.getFormat().order) ? getEffectiveDepthStencilAccess(m_expectedTextureLevel[mipLevelNdx]->getAccess(), mode) : |
| tcu::hasStencilComponent(resultAccess.getFormat().order) ? getEffectiveDepthStencilAccess(m_expectedTextureLevel[mipLevelNdx]->getAccess(), mode) : |
| m_expectedTextureLevel[mipLevelNdx]->getAccess(); |
| const tcu::ConstPixelBufferAccess unclampedLevel = tcu::hasDepthComponent(resultAccess.getFormat().order) ? getEffectiveDepthStencilAccess(m_unclampedExpectedTextureLevel[mipLevelNdx]->getAccess(), mode) : |
| tcu::hasStencilComponent(resultAccess.getFormat().order) ? getEffectiveDepthStencilAccess(m_unclampedExpectedTextureLevel[mipLevelNdx]->getAccess(), mode) : |
| m_unclampedExpectedTextureLevel[mipLevelNdx]->getAccess(); |
| const tcu::TextureFormat srcFormat = tcu::hasDepthComponent(resultAccess.getFormat().order) ? tcu::getEffectiveDepthStencilTextureFormat(mapVkFormat(m_params.src.image.format), mode) : |
| tcu::hasStencilComponent(resultAccess.getFormat().order) ? tcu::getEffectiveDepthStencilTextureFormat(mapVkFormat(m_params.src.image.format), mode) : |
| mapVkFormat(m_params.src.image.format); |
| |
| const tcu::TextureFormat dstFormat = result.getFormat(); |
| bool singleLevelOk = false; |
| std::vector <CopyRegion> mipLevelRegions; |
| |
| for (size_t regionNdx = 0u; regionNdx < m_params.regions.size(); regionNdx++) |
| if (m_params.regions.at(regionNdx).imageBlit.dstSubresource.mipLevel == mipLevelNdx) |
| mipLevelRegions.push_back(m_params.regions.at(regionNdx)); |
| |
| log << tcu::TestLog::Section("ClampedSourceImage", "Region with clamped edges on source image."); |
| |
| if (isFloatFormat(dstFormat)) |
| { |
| const bool srcIsSRGB = tcu::isSRGB(srcFormat); |
| const tcu::Vec4 srcMaxDiff = getFormatThreshold(srcFormat) * tcu::Vec4(srcIsSRGB ? 2.0f : 1.0f); |
| const tcu::Vec4 dstMaxDiff = getFormatThreshold(dstFormat); |
| const tcu::Vec4 threshold = ( srcMaxDiff + dstMaxDiff ) * ((m_params.filter == VK_FILTER_CUBIC_EXT)? 1.5f : 1.0f); |
| |
| singleLevelOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", clampedLevel, result, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| |
| if (!singleLevelOk) |
| { |
| log << tcu::TestLog::Section("NonClampedSourceImage", "Region with non-clamped edges on source image."); |
| singleLevelOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", unclampedLevel, result, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| } |
| } |
| else |
| { |
| tcu::UVec4 threshold; |
| // Calculate threshold depending on channel width of destination format. |
| const tcu::IVec4 dstBitDepth = tcu::getTextureFormatBitDepth(dstFormat); |
| const tcu::IVec4 srcBitDepth = tcu::getTextureFormatBitDepth(srcFormat); |
| for (deUint32 i = 0; i < 4; ++i) |
| threshold[i] = 1 + de::max(((1 << dstBitDepth[i]) - 1) / de::clamp((1 << srcBitDepth[i]) - 1, 1, 256), 1); |
| |
| singleLevelOk = tcu::intThresholdCompare(log, "Compare", "Result comparsion", clampedLevel, result, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| |
| if (!singleLevelOk) |
| { |
| log << tcu::TestLog::Section("NonClampedSourceImage", "Region with non-clamped edges on source image."); |
| singleLevelOk = tcu::intThresholdCompare(log, "Compare", "Result comparsion", unclampedLevel, result, threshold, tcu::COMPARE_LOG_RESULT); |
| log << tcu::TestLog::EndSection; |
| } |
| } |
| allLevelsOk &= singleLevelOk; |
| } |
| |
| return allLevelsOk; |
| } |
| |
| bool BlittingMipmaps::checkNearestFilteredResult (void) |
| { |
| bool allLevelsOk = true; |
| tcu::TestLog& log (m_context.getTestContext().getLog()); |
| |
| for (deUint32 mipLevelNdx = 0u; mipLevelNdx < m_params.mipLevels; mipLevelNdx++) |
| { |
| de::MovePtr<tcu::TextureLevel> resultLevel = readImage(*m_destination, m_params.dst.image, mipLevelNdx); |
| const tcu::ConstPixelBufferAccess& resultAccess = resultLevel->getAccess(); |
| |
| const tcu::Sampler::DepthStencilMode mode = tcu::hasDepthComponent(resultAccess.getFormat().order) ? tcu::Sampler::MODE_DEPTH : |
| tcu::hasStencilComponent(resultAccess.getFormat().order) ? tcu::Sampler::MODE_STENCIL : |
| tcu::Sampler::MODE_LAST; |
| const tcu::ConstPixelBufferAccess result = tcu::hasDepthComponent(resultAccess.getFormat().order) ? getEffectiveDepthStencilAccess(resultAccess, mode) : |
| tcu::hasStencilComponent(resultAccess.getFormat().order) ? getEffectiveDepthStencilAccess(resultAccess, mode) : |
| resultAccess; |
| const tcu::ConstPixelBufferAccess source = (m_params.singleCommand || mipLevelNdx == 0) ? // Read from source image |
| tcu::hasDepthComponent(resultAccess.getFormat().order) ? tcu::getEffectiveDepthStencilAccess(m_sourceTextureLevel->getAccess(), mode) : |
| tcu::hasStencilComponent(resultAccess.getFormat().order) ? tcu::getEffectiveDepthStencilAccess(m_sourceTextureLevel->getAccess(), mode) : |
| m_sourceTextureLevel->getAccess() |
| // Read from destination image |
| : tcu::hasDepthComponent(resultAccess.getFormat().order) ? tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[mipLevelNdx - 1u]->getAccess(), mode) : |
| tcu::hasStencilComponent(resultAccess.getFormat().order) ? tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[mipLevelNdx - 1u]->getAccess(), mode) : |
| m_expectedTextureLevel[mipLevelNdx - 1u]->getAccess(); |
| const tcu::TextureFormat dstFormat = result.getFormat(); |
| const tcu::TextureChannelClass dstChannelClass = tcu::getTextureChannelClass(dstFormat.type); |
| bool singleLevelOk = false; |
| std::vector <CopyRegion> mipLevelRegions; |
| |
| for (size_t regionNdx = 0u; regionNdx < m_params.regions.size(); regionNdx++) |
| if (m_params.regions.at(regionNdx).imageBlit.dstSubresource.mipLevel == mipLevelNdx) |
| mipLevelRegions.push_back(m_params.regions.at(regionNdx)); |
| |
| tcu::TextureLevel errorMaskStorage (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), result.getWidth(), result.getHeight(), result.getDepth()); |
| tcu::PixelBufferAccess errorMask = errorMaskStorage.getAccess(); |
| tcu::Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); |
| tcu::Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); |
| |
| tcu::clear(errorMask, tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0)); |
| |
| if (dstChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || |
| dstChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) |
| { |
| singleLevelOk = intNearestBlitCompare(source, result, errorMask, mipLevelRegions); |
| } |
| else |
| { |
| const tcu::Vec4 srcMaxDiff = getFloatOrFixedPointFormatThreshold(source.getFormat()); |
| const tcu::Vec4 dstMaxDiff = getFloatOrFixedPointFormatThreshold(result.getFormat()); |
| |
| singleLevelOk = floatNearestBlitCompare(source, result, srcMaxDiff, dstMaxDiff, errorMask, mipLevelRegions); |
| } |
| |
| if (dstFormat != tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)) |
| tcu::computePixelScaleBias(result, pixelScale, pixelBias); |
| |
| if (!singleLevelOk) |
| { |
| log << tcu::TestLog::ImageSet("Compare", "Result comparsion, level " + de::toString(mipLevelNdx)) |
| << tcu::TestLog::Image("Result", "Result", result, pixelScale, pixelBias) |
| << tcu::TestLog::Image("Reference", "Reference", source, pixelScale, pixelBias) |
| << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask) |
| << tcu::TestLog::EndImageSet; |
| } |
| else |
| { |
| log << tcu::TestLog::ImageSet("Compare", "Result comparsion, level " + de::toString(mipLevelNdx)) |
| << tcu::TestLog::Image("Result", "Result", result, pixelScale, pixelBias) |
| << tcu::TestLog::EndImageSet; |
| } |
| |
| allLevelsOk &= singleLevelOk; |
| } |
| |
| return allLevelsOk; |
| } |
| |
| tcu::TestStatus BlittingMipmaps::checkTestResult (tcu::ConstPixelBufferAccess result) |
| { |
| DE_UNREF(result); |
| DE_ASSERT(m_params.filter == VK_FILTER_NEAREST || m_params.filter == VK_FILTER_LINEAR || m_params.filter == VK_FILTER_CUBIC_EXT); |
| const std::string failMessage("Result image is incorrect"); |
| |
| if (m_params.filter != VK_FILTER_NEAREST) |
| { |
| if (!checkNonNearestFilteredResult()) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| else // NEAREST filtering |
| { |
| if (!checkNearestFilteredResult()) |
| return tcu::TestStatus::fail(failMessage); |
| } |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| void BlittingMipmaps::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel) |
| { |
| DE_ASSERT(src.getDepth() == dst.getDepth()); |
| |
| const MirrorMode mirrorMode = getMirrorMode(region.imageBlit.srcOffsets[0], |
| region.imageBlit.srcOffsets[1], |
| region.imageBlit.dstOffsets[0], |
| region.imageBlit.dstOffsets[1]); |
| |
| flipCoordinates(region, mirrorMode); |
| |
| const VkOffset3D srcOffset = region.imageBlit.srcOffsets[0]; |
| const VkOffset3D srcExtent = |
| { |
| region.imageBlit.srcOffsets[1].x - srcOffset.x, |
| region.imageBlit.srcOffsets[1].y - srcOffset.y, |
| region.imageBlit.srcOffsets[1].z - srcOffset.z |
| }; |
| const VkOffset3D dstOffset = region.imageBlit.dstOffsets[0]; |
| const VkOffset3D dstExtent = |
| { |
| region.imageBlit.dstOffsets[1].x - dstOffset.x, |
| region.imageBlit.dstOffsets[1].y - dstOffset.y, |
| region.imageBlit.dstOffsets[1].z - dstOffset.z |
| }; |
| |
| tcu::Sampler::FilterMode filter; |
| switch (m_params.filter) |
| { |
| case VK_FILTER_LINEAR: filter = tcu::Sampler::LINEAR; break; |
| case VK_FILTER_CUBIC_EXT: filter = tcu::Sampler::CUBIC; break; |
| case VK_FILTER_NEAREST: |
| default: filter = tcu::Sampler::NEAREST; break; |
| } |
| |
| if (tcu::isCombinedDepthStencilType(src.getFormat().type)) |
| { |
| DE_ASSERT(src.getFormat() == dst.getFormat()); |
| // Scale depth. |
| if (tcu::hasDepthComponent(src.getFormat().order)) |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcExtent.x, srcExtent.y), tcu::Sampler::MODE_DEPTH); |
| const tcu::PixelBufferAccess dstSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_DEPTH); |
| tcu::scale(dstSubRegion, srcSubRegion, filter); |
| |
| if (filter != tcu::Sampler::NEAREST) |
| { |
| const tcu::ConstPixelBufferAccess depthSrc = getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_DEPTH); |
| const tcu::PixelBufferAccess unclampedSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(m_unclampedExpectedTextureLevel[0]->getAccess(), dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_DEPTH); |
| scaleFromWholeSrcBuffer(unclampedSubRegion, depthSrc, srcOffset, srcExtent, filter); |
| } |
| } |
| |
| // Scale stencil. |
| if (tcu::hasStencilComponent(src.getFormat().order)) |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcExtent.x, srcExtent.y), tcu::Sampler::MODE_STENCIL); |
| const tcu::PixelBufferAccess dstSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_STENCIL); |
| blit(dstSubRegion, srcSubRegion, filter, mirrorMode); |
| |
| if (filter != tcu::Sampler::NEAREST) |
| { |
| const tcu::ConstPixelBufferAccess stencilSrc = getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_STENCIL); |
| const tcu::PixelBufferAccess unclampedSubRegion = getEffectiveDepthStencilAccess(tcu::getSubregion(m_unclampedExpectedTextureLevel[0]->getAccess(), dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_STENCIL); |
| scaleFromWholeSrcBuffer(unclampedSubRegion, stencilSrc, srcOffset, srcExtent, filter); |
| } |
| } |
| } |
| else |
| { |
| for (int layerNdx = 0u; layerNdx < src.getDepth(); layerNdx++) |
| { |
| const tcu::ConstPixelBufferAccess srcSubRegion = tcu::getSubregion(src, srcOffset.x, srcOffset.y, layerNdx, srcExtent.x, srcExtent.y, 1); |
| const tcu::PixelBufferAccess dstSubRegion = tcu::getSubregion(dst, dstOffset.x, dstOffset.y, layerNdx, dstExtent.x, dstExtent.y, 1); |
| blit(dstSubRegion, srcSubRegion, filter, mirrorMode); |
| |
| if (filter != tcu::Sampler::NEAREST) |
| { |
| const tcu::PixelBufferAccess unclampedSubRegion = tcu::getSubregion(m_unclampedExpectedTextureLevel[mipLevel]->getAccess(), dstOffset.x, dstOffset.y, layerNdx, dstExtent.x, dstExtent.y, 1); |
| scaleFromWholeSrcBuffer(unclampedSubRegion, srcSubRegion, srcOffset, srcExtent, filter); |
| } |
| } |
| } |
| } |
| |
| void BlittingMipmaps::generateExpectedResult (void) |
| { |
| const tcu::ConstPixelBufferAccess src = m_sourceTextureLevel->getAccess(); |
| const tcu::ConstPixelBufferAccess dst = m_destinationTextureLevel->getAccess(); |
| |
| for (deUint32 mipLevelNdx = 0u; mipLevelNdx < m_params.mipLevels; mipLevelNdx++) |
| m_expectedTextureLevel[mipLevelNdx] = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth() >> mipLevelNdx, dst.getHeight() >> mipLevelNdx, dst.getDepth())); |
| |
| tcu::copy(m_expectedTextureLevel[0]->getAccess(), src); |
| |
| if (m_params.filter != VK_FILTER_NEAREST) |
| { |
| for (deUint32 mipLevelNdx = 0u; mipLevelNdx < m_params.mipLevels; mipLevelNdx++) |
| m_unclampedExpectedTextureLevel[mipLevelNdx] = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth() >> mipLevelNdx, dst.getHeight() >> mipLevelNdx, dst.getDepth())); |
| |
| tcu::copy(m_unclampedExpectedTextureLevel[0]->getAccess(), src); |
| } |
| |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| CopyRegion region = m_params.regions[i]; |
| copyRegionToTextureLevel(m_expectedTextureLevel[m_params.regions[i].imageBlit.srcSubresource.mipLevel]->getAccess(), m_expectedTextureLevel[m_params.regions[i].imageBlit.dstSubresource.mipLevel]->getAccess(), region, m_params.regions[i].imageBlit.dstSubresource.mipLevel); |
| } |
| } |
| |
| class BlitMipmapTestCase : public vkt::TestCase |
| { |
| public: |
| BlitMipmapTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams params) |
| : vkt::TestCase (testCtx, name, description) |
| , m_params (params) |
| {} |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new BlittingMipmaps(context, m_params); |
| } |
| |
| virtual void checkSupport (Context& context) const |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const VkPhysicalDevice vkPhysDevice = context.getPhysicalDevice(); |
| { |
| VkImageFormatProperties properties; |
| if (context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.src.image.format, |
| VK_IMAGE_TYPE_2D, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT, |
| 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) |
| { |
| TCU_THROW(NotSupportedError, "Format not supported"); |
| } |
| else if ((m_params.src.image.extent.width > properties.maxExtent.width) || |
| (m_params.src.image.extent.height > properties.maxExtent.height) || |
| (m_params.src.image.extent.depth > properties.maxArrayLayers)) |
| { |
| TCU_THROW(NotSupportedError, "Image size not supported"); |
| } |
| } |
| |
| { |
| VkImageFormatProperties properties; |
| if (context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.dst.image.format, |
| VK_IMAGE_TYPE_2D, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, |
| 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) |
| { |
| TCU_THROW(NotSupportedError, "Format not supported"); |
| } |
| else if ((m_params.dst.image.extent.width > properties.maxExtent.width) || |
| (m_params.dst.image.extent.height > properties.maxExtent.height) || |
| (m_params.dst.image.extent.depth > properties.maxArrayLayers)) |
| { |
| TCU_THROW(NotSupportedError, "Image size not supported"); |
| } |
| else if (m_params.mipLevels > properties.maxMipLevels) |
| { |
| TCU_THROW(NotSupportedError, "Number of mip levels not supported"); |
| } |
| else if ((m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2) && |
| (!context.isDeviceFunctionalitySupported("VK_KHR_copy_commands2"))) |
| { |
| TCU_THROW(NotSupportedError, "VK_KHR_copy_commands2 is not supported"); |
| } |
| } |
| |
| const VkFormatProperties srcFormatProperties = getPhysicalDeviceFormatProperties (vki, vkPhysDevice, m_params.src.image.format); |
| if (!(srcFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) |
| { |
| TCU_THROW(NotSupportedError, "Format feature blit source not supported"); |
| } |
| |
| const VkFormatProperties dstFormatProperties = getPhysicalDeviceFormatProperties (vki, vkPhysDevice, m_params.dst.image.format); |
| if (!(dstFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) |
| { |
| TCU_THROW(NotSupportedError, "Format feature blit destination not supported"); |
| } |
| |
| if (m_params.filter == VK_FILTER_LINEAR && !(srcFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) |
| TCU_THROW(NotSupportedError, "Source format feature sampled image filter linear not supported"); |
| |
| if (m_params.filter == VK_FILTER_CUBIC_EXT) |
| { |
| context.requireDeviceFunctionality("VK_EXT_filter_cubic"); |
| |
| if (!(srcFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) |
| { |
| TCU_THROW(NotSupportedError, "Source format feature sampled image filter cubic not supported"); |
| } |
| } |
| } |
| |
| private: |
| TestParams m_params; |
| }; |
| |
| // Resolve image to image. |
| |
| enum ResolveImageToImageOptions{NO_OPTIONAL_OPERATION, COPY_MS_IMAGE_TO_MS_IMAGE, COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE}; |
| class ResolveImageToImage : public CopiesAndBlittingTestInstance |
| { |
| public: |
| ResolveImageToImage (Context& context, |
| TestParams params, |
| const ResolveImageToImageOptions options); |
| virtual tcu::TestStatus iterate (void); |
| protected: |
| virtual tcu::TestStatus checkTestResult (tcu::ConstPixelBufferAccess result = tcu::ConstPixelBufferAccess()); |
| void copyMSImageToMSImage (deUint32 copyArraySize); |
| tcu::TestStatus checkIntermediateCopy (void); |
| private: |
| Move<VkImage> m_multisampledImage; |
| de::MovePtr<Allocation> m_multisampledImageAlloc; |
| |
| Move<VkImage> m_destination; |
| de::MovePtr<Allocation> m_destinationImageAlloc; |
| |
| Move<VkImage> m_multisampledCopyImage; |
| de::MovePtr<Allocation> m_multisampledCopyImageAlloc; |
| |
| const ResolveImageToImageOptions m_options; |
| |
| virtual void copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, |
| tcu::PixelBufferAccess dst, |
| CopyRegion region, |
| deUint32 mipLevel = 0u); |
| }; |
| |
| ResolveImageToImage::ResolveImageToImage (Context& context, TestParams params, const ResolveImageToImageOptions options) |
| : CopiesAndBlittingTestInstance (context, params) |
| , m_options (options) |
| { |
| const InstanceInterface& vki = m_context.getInstanceInterface(); |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkPhysicalDevice vkPhysDevice = m_context.getPhysicalDevice(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = m_context.getDefaultAllocator(); |
| |
| const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; |
| Move<VkRenderPass> renderPass; |
| |
| Move<VkShaderModule> vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0); |
| Move<VkShaderModule> fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0); |
| std::vector<tcu::Vec4> vertices; |
| |
| Move<VkBuffer> vertexBuffer; |
| de::MovePtr<Allocation> vertexBufferAlloc; |
| |
| Move<VkPipelineLayout> pipelineLayout; |
| Move<VkPipeline> graphicsPipeline; |
| |
| const VkSampleCountFlagBits rasterizationSamples = m_params.samples; |
| |
| // Create color image. |
| { |
| VkImageCreateInfo colorImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.src.image), // VkImageCreateFlags flags; |
| m_params.src.image.imageType, // VkImageType imageType; |
| m_params.src.image.format, // VkFormat format; |
| getExtent3D(m_params.src.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.src.image), // deUint32 arrayLayers; |
| rasterizationSamples, // VkSampleCountFlagBits samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT // VkImageUsageFlags usage; |
| | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
| | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_multisampledImage = createImage(vk, vkDevice, &colorImageParams); |
| |
| // Allocate and bind color image memory. |
| m_multisampledImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_multisampledImage, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_multisampledImage, m_multisampledImageAlloc->getMemory(), m_multisampledImageAlloc->getOffset())); |
| |
| switch (m_options) |
| { |
| case COPY_MS_IMAGE_TO_MS_IMAGE: |
| { |
| colorImageParams.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| m_multisampledCopyImage = createImage(vk, vkDevice, &colorImageParams); |
| // Allocate and bind color image memory. |
| m_multisampledCopyImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_multisampledCopyImage, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_multisampledCopyImage, m_multisampledCopyImageAlloc->getMemory(), m_multisampledCopyImageAlloc->getOffset())); |
| break; |
| } |
| |
| case COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE: |
| { |
| colorImageParams.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| colorImageParams.arrayLayers = getArraySize(m_params.dst.image); |
| m_multisampledCopyImage = createImage(vk, vkDevice, &colorImageParams); |
| // Allocate and bind color image memory. |
| m_multisampledCopyImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_multisampledCopyImage, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_multisampledCopyImage, m_multisampledCopyImageAlloc->getMemory(), m_multisampledCopyImageAlloc->getOffset())); |
| break; |
| } |
| |
| default : |
| break; |
| } |
| } |
| |
| // Create destination image. |
| { |
| const VkImageCreateInfo destinationImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| getCreateFlags(m_params.dst.image), // VkImageCreateFlags flags; |
| m_params.dst.image.imageType, // VkImageType imageType; |
| m_params.dst.image.format, // VkFormat format; |
| getExtent3D(m_params.dst.image), // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| getArraySize(m_params.dst.image), // deUint32 arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| m_destination = createImage(vk, vkDevice, &destinationImageParams); |
| m_destinationImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset())); |
| } |
| |
| // Barriers for copying image to buffer |
| VkImageMemoryBarrier srcImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_multisampledImage.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.src.image) // deUint32 arraySize; |
| } |
| }; |
| |
| // Create render pass. |
| { |
| const VkAttachmentDescription attachmentDescriptions[1] = |
| { |
| { |
| 0u, // VkAttachmentDescriptionFlags flags; |
| m_params.src.image.format, // VkFormat format; |
| rasterizationSamples, // VkSampleCountFlagBits samples; |
| VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; |
| }, |
| }; |
| |
| const VkAttachmentReference colorAttachmentReference = |
| { |
| 0u, // deUint32 attachment; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; |
| }; |
| |
| const VkSubpassDescription subpassDescription = |
| { |
| 0u, // VkSubpassDescriptionFlags flags; |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; |
| 0u, // deUint32 inputAttachmentCount; |
| DE_NULL, // const VkAttachmentReference* pInputAttachments; |
| 1u, // deUint32 colorAttachmentCount; |
| &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; |
| DE_NULL, // const VkAttachmentReference* pResolveAttachments; |
| DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; |
| 0u, // deUint32 preserveAttachmentCount; |
| DE_NULL // const VkAttachmentReference* pPreserveAttachments; |
| }; |
| |
| const VkRenderPassCreateInfo renderPassParams = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkRenderPassCreateFlags flags; |
| 1u, // deUint32 attachmentCount; |
| attachmentDescriptions, // const VkAttachmentDescription* pAttachments; |
| 1u, // deUint32 subpassCount; |
| &subpassDescription, // const VkSubpassDescription* pSubpasses; |
| 0u, // deUint32 dependencyCount; |
| DE_NULL // const VkSubpassDependency* pDependencies; |
| }; |
| |
| renderPass = createRenderPass(vk, vkDevice, &renderPassParams); |
| } |
| |
| // Create pipeline layout |
| { |
| const VkPipelineLayoutCreateInfo pipelineLayoutParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineLayoutCreateFlags flags; |
| 0u, // deUint32 setLayoutCount; |
| DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; |
| 0u, // deUint32 pushConstantRangeCount; |
| DE_NULL // const VkPushConstantRange* pPushConstantRanges; |
| }; |
| |
| pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); |
| } |
| |
| // Create upper half triangle. |
| { |
| const tcu::Vec4 a (-1.0, -1.0, 0.0, 1.0); |
| const tcu::Vec4 b (1.0, -1.0, 0.0, 1.0); |
| const tcu::Vec4 c (1.0, 1.0, 0.0, 1.0); |
| // Add triangle. |
| vertices.push_back(a); |
| vertices.push_back(c); |
| vertices.push_back(b); |
| } |
| |
| // Create vertex buffer. |
| { |
| const VkDeviceSize vertexDataSize = vertices.size() * sizeof(tcu::Vec4); |
| const VkBufferCreateInfo vertexBufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| vertexDataSize, // VkDeviceSize size; |
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); |
| vertexBufferAlloc = allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *vertexBuffer, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind); |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset())); |
| |
| // Load vertices into vertex buffer. |
| deMemcpy(vertexBufferAlloc->getHostPtr(), vertices.data(), (size_t)vertexDataSize); |
| flushAlloc(vk, vkDevice, *vertexBufferAlloc); |
| } |
| |
| { |
| Move<VkFramebuffer> framebuffer; |
| Move<VkImageView> sourceAttachmentView; |
| |
| // Create color attachment view. |
| { |
| const VkImageViewCreateInfo colorAttachmentViewParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkImageViewCreateFlags flags; |
| *m_multisampledImage, // VkImage image; |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; |
| m_params.src.image.format, // VkFormat format; |
| componentMappingRGBA, // VkComponentMapping components; |
| { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; |
| }; |
| sourceAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams); |
| } |
| |
| // Create framebuffer |
| { |
| const VkImageView attachments[1] = |
| { |
| *sourceAttachmentView, |
| }; |
| |
| const VkFramebufferCreateInfo framebufferParams = |
| { |
| VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkFramebufferCreateFlags flags; |
| *renderPass, // VkRenderPass renderPass; |
| 1u, // deUint32 attachmentCount; |
| attachments, // const VkImageView* pAttachments; |
| m_params.src.image.extent.width, // deUint32 width; |
| m_params.src.image.extent.height, // deUint32 height; |
| 1u // deUint32 layers; |
| }; |
| |
| framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); |
| } |
| |
| // Create pipeline |
| { |
| const std::vector<VkViewport> viewports (1, makeViewport(m_params.src.image.extent)); |
| const std::vector<VkRect2D> scissors (1, makeRect2D(m_params.src.image.extent)); |
| |
| const VkPipelineMultisampleStateCreateInfo multisampleStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineMultisampleStateCreateFlags flags; |
| rasterizationSamples, // VkSampleCountFlagBits rasterizationSamples; |
| VK_FALSE, // VkBool32 sampleShadingEnable; |
| 0.0f, // float minSampleShading; |
| DE_NULL, // const VkSampleMask* pSampleMask; |
| VK_FALSE, // VkBool32 alphaToCoverageEnable; |
| VK_FALSE // VkBool32 alphaToOneEnable; |
| }; |
| |
| graphicsPipeline = makeGraphicsPipeline(vk, // const DeviceInterface& vk |
| vkDevice, // const VkDevice device |
| *pipelineLayout, // const VkPipelineLayout pipelineLayout |
| *vertexShaderModule, // const VkShaderModule vertexShaderModule |
| DE_NULL, // const VkShaderModule tessellationControlModule |
| DE_NULL, // const VkShaderModule tessellationEvalModule |
| DE_NULL, // const VkShaderModule geometryShaderModule |
| *fragmentShaderModule, // const VkShaderModule fragmentShaderModule |
| *renderPass, // const VkRenderPass renderPass |
| viewports, // const std::vector<VkViewport>& viewports |
| scissors, // const std::vector<VkRect2D>& scissors |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology |
| 0u, // const deUint32 subpass |
| 0u, // const deUint32 patchControlPoints |
| DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo |
| DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo |
| &multisampleStateParams); // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo |
| } |
| |
| // Create command buffer |
| { |
| beginCommandBuffer(vk, *m_cmdBuffer, 0u); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &srcImageBarrier); |
| beginRenderPass(vk, *m_cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, m_params.src.image.extent.width, m_params.src.image.extent.height), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); |
| |
| const VkDeviceSize vertexBufferOffset = 0u; |
| |
| vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline); |
| vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset); |
| vk.cmdDraw(*m_cmdBuffer, (deUint32)vertices.size(), 1, 0, 0); |
| |
| endRenderPass(vk, *m_cmdBuffer); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| } |
| |
| // Queue submit. |
| { |
| const VkQueue queue = m_context.getUniversalQueue(); |
| submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer); |
| } |
| } |
| } |
| |
| tcu::TestStatus ResolveImageToImage::iterate (void) |
| { |
| const tcu::TextureFormat srcTcuFormat = mapVkFormat(m_params.src.image.format); |
| const tcu::TextureFormat dstTcuFormat = mapVkFormat(m_params.dst.image.format); |
| |
| // upload the destination image |
| m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dstTcuFormat, |
| (int)m_params.dst.image.extent.width, |
| (int)m_params.dst.image.extent.height, |
| (int)m_params.dst.image.extent.depth)); |
| generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth); |
| uploadImage(m_destinationTextureLevel->getAccess(), m_destination.get(), m_params.dst.image); |
| |
| m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(srcTcuFormat, |
| (int)m_params.src.image.extent.width, |
| (int)m_params.src.image.extent.height, |
| (int)m_params.dst.image.extent.depth)); |
| |
| generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.dst.image.extent.depth, FILL_MODE_MULTISAMPLE); |
| generateExpectedResult(); |
| |
| VkImage sourceImage = m_multisampledImage.get(); |
| deUint32 sourceArraySize = getArraySize(m_params.src.image); |
| |
| switch (m_options) |
| { |
| case COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE: |
| // Duplicate the multisampled image to a multisampled image array |
| sourceArraySize = getArraySize(m_params.dst.image); // fall through |
| case COPY_MS_IMAGE_TO_MS_IMAGE: |
| copyMSImageToMSImage(sourceArraySize); |
| sourceImage = m_multisampledCopyImage.get(); |
| break; |
| default: |
| break; |
| } |
| |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| std::vector<VkImageResolve> imageResolves; |
| std::vector<VkImageResolve2KHR> imageResolves2KHR; |
| for (deUint32 i = 0; i < m_params.regions.size(); i++) |
| { |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| imageResolves.push_back(m_params.regions[i].imageResolve); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| imageResolves2KHR.push_back(convertvkImageResolveTovkImageResolve2KHR(m_params.regions[i].imageResolve)); |
| } |
| } |
| |
| const VkImageMemoryBarrier imageBarriers[] = |
| { |
| // source image |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| m_params.src.image.operationLayout, // VkImageLayout oldLayout; |
| m_params.src.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| sourceImage, // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(srcTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| sourceArraySize // deUint32 arraySize; |
| } |
| }, |
| // destination image |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; |
| m_params.dst.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.dst.image) // deUint32 arraySize; |
| } |
| }, |
| }; |
| |
| const VkImageMemoryBarrier postImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; |
| m_params.dst.image.operationLayout, // VkImageLayout oldLayout; |
| m_params.dst.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_destination.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(dstTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.dst.image) // deUint32 arraySize; |
| } |
| }; |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdResolveImage(*m_cmdBuffer, sourceImage, m_params.src.image.operationLayout, m_destination.get(), m_params.dst.image.operationLayout, (deUint32)m_params.regions.size(), imageResolves.data()); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkResolveImageInfo2KHR ResolveImageInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| sourceImage, // VkImage srcImage; |
| m_params.src.image.operationLayout, // VkImageLayout srcImageLayout; |
| m_destination.get(), // VkImage dstImage; |
| m_params.dst.image.operationLayout, // VkImageLayout dstImageLayout; |
| (deUint32)m_params.regions.size(), // uint32_t regionCount; |
| imageResolves2KHR.data() // const VkImageResolve2KHR* pRegions; |
| }; |
| vk.cmdResolveImage2(*m_cmdBuffer, &ResolveImageInfo2KHR); |
| } |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer); |
| |
| de::MovePtr<tcu::TextureLevel> resultTextureLevel = readImage(*m_destination, m_params.dst.image); |
| |
| if (m_options == COPY_MS_IMAGE_TO_MS_IMAGE || m_options == COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE) |
| { |
| // Verify the intermediate multisample copy operation happens properly instead of, for example, shuffling samples around or |
| // resolving the image and giving every sample the same value. |
| const auto intermediateResult = checkIntermediateCopy(); |
| if (intermediateResult.getCode() != QP_TEST_RESULT_PASS) |
| return intermediateResult; |
| } |
| |
| return checkTestResult(resultTextureLevel->getAccess()); |
| } |
| |
| tcu::TestStatus ResolveImageToImage::checkTestResult (tcu::ConstPixelBufferAccess result) |
| { |
| const tcu::ConstPixelBufferAccess expected = m_expectedTextureLevel[0]->getAccess(); |
| const float fuzzyThreshold = 0.01f; |
| |
| for (int arrayLayerNdx = 0; arrayLayerNdx < (int)getArraySize(m_params.dst.image); ++arrayLayerNdx) |
| { |
| const tcu::ConstPixelBufferAccess expectedSub = getSubregion (expected, 0, 0, arrayLayerNdx, expected.getWidth(), expected.getHeight(), 1u); |
| const tcu::ConstPixelBufferAccess resultSub = getSubregion (result, 0, 0, arrayLayerNdx, result.getWidth(), result.getHeight(), 1u); |
| if (!tcu::fuzzyCompare(m_context.getTestContext().getLog(), "Compare", "Result comparsion", expectedSub, resultSub, fuzzyThreshold, tcu::COMPARE_LOG_RESULT)) |
| return tcu::TestStatus::fail("CopiesAndBlitting test"); |
| } |
| |
| return tcu::TestStatus::pass("CopiesAndBlitting test"); |
| } |
| |
| void ResolveImageToImage::copyRegionToTextureLevel(tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region, deUint32 mipLevel) |
| { |
| DE_UNREF(mipLevel); |
| |
| VkOffset3D srcOffset = region.imageResolve.srcOffset; |
| srcOffset.z = region.imageResolve.srcSubresource.baseArrayLayer; |
| VkOffset3D dstOffset = region.imageResolve.dstOffset; |
| dstOffset.z = region.imageResolve.dstSubresource.baseArrayLayer; |
| VkExtent3D extent = region.imageResolve.extent; |
| extent.depth = region.imageResolve.srcSubresource.layerCount; |
| |
| const tcu::ConstPixelBufferAccess srcSubRegion = getSubregion (src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth); |
| // CopyImage acts like a memcpy. Replace the destination format with the srcformat to use a memcpy. |
| const tcu::PixelBufferAccess dstWithSrcFormat (srcSubRegion.getFormat(), dst.getSize(), dst.getDataPtr()); |
| const tcu::PixelBufferAccess dstSubRegion = getSubregion (dstWithSrcFormat, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth); |
| |
| tcu::copy(dstSubRegion, srcSubRegion); |
| } |
| |
| tcu::TestStatus ResolveImageToImage::checkIntermediateCopy (void) |
| { |
| const auto& vkd = m_context.getDeviceInterface(); |
| const auto device = m_context.getDevice(); |
| const auto queue = m_context.getUniversalQueue(); |
| const auto queueIndex = m_context.getUniversalQueueFamilyIndex(); |
| auto& alloc = m_context.getDefaultAllocator(); |
| const auto currentLayout = m_params.src.image.operationLayout; |
| const auto numDstLayers = getArraySize(m_params.dst.image); |
| const auto numInputAttachments = numDstLayers + 1u; // For the source image. |
| constexpr auto numSets = 2u; // 1 for the output buffer, 1 for the input attachments. |
| const auto fbWidth = m_params.src.image.extent.width; |
| const auto fbHeight = m_params.src.image.extent.height; |
| |
| // Push constants. |
| const std::array<int, 3> pushConstantData = |
| {{ |
| static_cast<int>(fbWidth), |
| static_cast<int>(fbHeight), |
| static_cast<int>(m_params.samples), |
| }}; |
| const auto pushConstantSize = static_cast<deUint32>(pushConstantData.size() * sizeof(decltype(pushConstantData)::value_type)); |
| |
| // Shader modules. |
| const auto vertexModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u); |
| const auto verificationModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("verify"), 0u); |
| |
| // Descriptor sets. |
| DescriptorPoolBuilder poolBuilder; |
| poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, numInputAttachments); |
| const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numSets); |
| |
| DescriptorSetLayoutBuilder layoutBuilderBuffer; |
| layoutBuilderBuffer.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT); |
| const auto outputBufferSetLayout = layoutBuilderBuffer.build(vkd, device); |
| |
| DescriptorSetLayoutBuilder layoutBuilderAttachments; |
| for (deUint32 i = 0u; i < numInputAttachments; ++i) |
| layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT); |
| const auto inputAttachmentsSetLayout = layoutBuilderAttachments.build(vkd, device); |
| |
| const auto descriptorSetBuffer = makeDescriptorSet(vkd, device, descriptorPool.get(), outputBufferSetLayout.get()); |
| const auto descriptorSetAttachments = makeDescriptorSet(vkd, device, descriptorPool.get(), inputAttachmentsSetLayout.get()); |
| |
| // Array with raw descriptor sets. |
| const std::array<VkDescriptorSet, numSets> descriptorSets = |
| {{ |
| descriptorSetBuffer.get(), |
| descriptorSetAttachments.get(), |
| }}; |
| |
| // Pipeline layout. |
| const std::array<VkDescriptorSetLayout, numSets> setLayouts = |
| {{ |
| outputBufferSetLayout.get(), |
| inputAttachmentsSetLayout.get(), |
| }}; |
| |
| const VkPushConstantRange pushConstantRange = |
| { |
| VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags; |
| 0u, // deUint32 offset; |
| pushConstantSize, // deUint32 size; |
| }; |
| |
| const VkPipelineLayoutCreateInfo pipelineLayoutInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; |
| nullptr, // const void* pNext; |
| 0u, // VkPipelineLayoutCreateFlags flags; |
| static_cast<deUint32>(setLayouts.size()), // deUint32 setLayoutCount; |
| setLayouts.data(), // const VkDescriptorSetLayout* pSetLayouts; |
| 1u, // deUint32 pushConstantRangeCount; |
| &pushConstantRange, // const VkPushConstantRange* pPushConstantRanges; |
| }; |
| |
| const auto pipelineLayout = createPipelineLayout(vkd, device, &pipelineLayoutInfo); |
| |
| // Render pass. |
| const VkAttachmentDescription commonAttachmentDescription = |
| { |
| 0u, // VkAttachmentDescriptionFlags flags; |
| m_params.src.image.format, // VkFormat format; |
| m_params.samples, // VkSampleCountFlagBits samples; |
| VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; |
| currentLayout, // VkImageLayout initialLayout; |
| currentLayout, // VkImageLayout finalLayout; |
| }; |
| const std::vector<VkAttachmentDescription> attachmentDescriptions(numInputAttachments, commonAttachmentDescription); |
| |
| std::vector<VkAttachmentReference> inputAttachmentReferences; |
| inputAttachmentReferences.reserve(numInputAttachments); |
| for (deUint32 i = 0u; i < numInputAttachments; ++i) |
| { |
| const VkAttachmentReference reference = { i, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; |
| inputAttachmentReferences.push_back(reference); |
| } |
| |
| const VkSubpassDescription subpassDescription = |
| { |
| 0u, // VkSubpassDescriptionFlags flags; |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; |
| static_cast<deUint32>(inputAttachmentReferences.size()), // deUint32 inputAttachmentCount; |
| inputAttachmentReferences.data(), // const VkAttachmentReference* pInputAttachments; |
| 0u, // deUint32 colorAttachmentCount; |
| nullptr, // const VkAttachmentReference* pColorAttachments; |
| nullptr, // const VkAttachmentReference* pResolveAttachments; |
| nullptr, // const VkAttachmentReference* pDepthStencilAttachment; |
| 0u, // deUint32 preserveAttachmentCount; |
| nullptr, // const deUint32* pPreserveAttachments; |
| }; |
| |
| const VkRenderPassCreateInfo renderPassInfo = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; |
| nullptr, // const void* pNext; |
| 0u, // VkRenderPassCreateFlags flags; |
| static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount; |
| attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments; |
| 1u, // deUint32 subpassCount; |
| &subpassDescription, // const VkSubpassDescription* pSubpasses; |
| 0u, // deUint32 dependencyCount; |
| nullptr, // const VkSubpassDependency* pDependencies; |
| }; |
| |
| const auto renderPass = createRenderPass(vkd, device, &renderPassInfo); |
| |
| // Framebuffer. |
| std::vector<Move<VkImageView>> imageViews; |
| std::vector<VkImageView> imageViewsRaw; |
| |
| imageViews.push_back(makeImageView(vkd, device, m_multisampledImage.get(), VK_IMAGE_VIEW_TYPE_2D, m_params.src.image.format, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))); |
| for (deUint32 i = 0u; i < numDstLayers; ++i) |
| { |
| const auto subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, i, 1u); |
| imageViews.push_back(makeImageView(vkd, device, m_multisampledCopyImage.get(), VK_IMAGE_VIEW_TYPE_2D, m_params.dst.image.format, subresourceRange)); |
| } |
| |
| imageViewsRaw.reserve(imageViews.size()); |
| std::transform(begin(imageViews), end(imageViews), std::back_inserter(imageViewsRaw), [](const Move<VkImageView>& ptr) { return ptr.get(); }); |
| |
| const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), static_cast<deUint32>(imageViewsRaw.size()), imageViewsRaw.data(), fbWidth, fbHeight); |
| |
| // Storage buffer. |
| const auto bufferCount = static_cast<size_t>(fbWidth * fbHeight * m_params.samples); |
| const auto bufferSize = static_cast<VkDeviceSize>(bufferCount * sizeof(deInt32)); |
| BufferWithMemory buffer (vkd, device, alloc, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible); |
| auto& bufferAlloc = buffer.getAllocation(); |
| void* bufferData = bufferAlloc.getHostPtr(); |
| |
| // Update descriptor sets. |
| DescriptorSetUpdateBuilder updater; |
| |
| const auto bufferInfo = makeDescriptorBufferInfo(buffer.get(), 0ull, bufferSize); |
| updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo); |
| |
| std::vector<VkDescriptorImageInfo> imageInfos; |
| imageInfos.reserve(imageViewsRaw.size()); |
| for (size_t i = 0; i < imageViewsRaw.size(); ++i) |
| imageInfos.push_back(makeDescriptorImageInfo(DE_NULL, imageViewsRaw[i], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); |
| |
| for (size_t i = 0; i < imageInfos.size(); ++i) |
| updater.writeSingle(descriptorSetAttachments.get(), DescriptorSetUpdateBuilder::Location::binding(static_cast<deUint32>(i)), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[i]); |
| |
| updater.update(vkd, device); |
| |
| // Vertex buffer. |
| std::vector<tcu::Vec4> fullScreenQuad; |
| { |
| // Full screen quad so every framebuffer pixel and sample location is verified by the shader. |
| const tcu::Vec4 topLeft (-1.0f, -1.0f, 0.0f, 1.0f); |
| const tcu::Vec4 topRight ( 1.0f, -1.0f, 0.0f, 1.0f); |
| const tcu::Vec4 bottomLeft (-1.0f, 1.0f, 0.0f, 1.0f); |
| const tcu::Vec4 bottomRight ( 1.0f, 1.0f, 0.0f, 1.0f); |
| |
| fullScreenQuad.reserve(6u); |
| fullScreenQuad.push_back(topLeft); |
| fullScreenQuad.push_back(topRight); |
| fullScreenQuad.push_back(bottomRight); |
| fullScreenQuad.push_back(topLeft); |
| fullScreenQuad.push_back(bottomRight); |
| fullScreenQuad.push_back(bottomLeft); |
| } |
| |
| const auto vertexBufferSize = static_cast<VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type)); |
| const auto vertexBufferInfo = makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); |
| const BufferWithMemory vertexBuffer (vkd, device, alloc, vertexBufferInfo, MemoryRequirement::HostVisible); |
| const auto vertexBufferHandler = vertexBuffer.get(); |
| auto& vertexBufferAlloc = vertexBuffer.getAllocation(); |
| void* vertexBufferData = vertexBufferAlloc.getHostPtr(); |
| const VkDeviceSize vertexBufferOffset = 0ull; |
| |
| deMemcpy(vertexBufferData, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize)); |
| flushAlloc(vkd, device, vertexBufferAlloc); |
| |
| // Graphics pipeline. |
| const std::vector<VkViewport> viewports (1, makeViewport(m_params.src.image.extent)); |
| const std::vector<VkRect2D> scissors (1, makeRect2D(m_params.src.image.extent)); |
| |
| const VkPipelineMultisampleStateCreateInfo multisampleStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; |
| nullptr, // const void* pNext; |
| 0u, // VkPipelineMultisampleStateCreateFlags flags; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; |
| VK_FALSE, // VkBool32 sampleShadingEnable; |
| 0.0f, // float minSampleShading; |
| nullptr, // const VkSampleMask* pSampleMask; |
| VK_FALSE, // VkBool32 alphaToCoverageEnable; |
| VK_FALSE // VkBool32 alphaToOneEnable; |
| }; |
| |
| const auto graphicsPipeline = makeGraphicsPipeline( |
| vkd, // const DeviceInterface& vk |
| device, // const VkDevice device |
| pipelineLayout.get(), // const VkPipelineLayout pipelineLayout |
| vertexModule.get(), // const VkShaderModule vertexShaderModule |
| DE_NULL, // const VkShaderModule tessellationControlModule |
| DE_NULL, // const VkShaderModule tessellationEvalModule |
| DE_NULL, // const VkShaderModule geometryShaderModule |
| verificationModule.get(), // const VkShaderModule fragmentShaderModule |
| renderPass.get(), // const VkRenderPass renderPass |
| viewports, // const std::vector<VkViewport>& viewports |
| scissors, // const std::vector<VkRect2D>& scissors |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology |
| 0u, // const deUint32 subpass |
| 0u, // const deUint32 patchControlPoints |
| nullptr, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo |
| nullptr, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo |
| &multisampleStateParams); // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo |
| |
| // Command buffer. |
| const auto cmdPool = makeCommandPool(vkd, device, queueIndex); |
| const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| const auto cmdBuffer = cmdBufferPtr.get(); |
| |
| // Make sure multisample copy data is available to the fragment shader. |
| const auto imagesBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT); |
| |
| // Make sure verification buffer data is available on the host. |
| const auto bufferBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT); |
| |
| // Record and submit command buffer. |
| beginCommandBuffer(vkd, cmdBuffer); |
| vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u, &imagesBarrier, 0u, nullptr, 0u, nullptr); |
| beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), makeRect2D(m_params.src.image.extent)); |
| vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get()); |
| vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBufferHandler, &vertexBufferOffset); |
| vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0u, pushConstantSize, pushConstantData.data()); |
| vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, static_cast<deUint32>(descriptorSets.size()), descriptorSets.data(), 0u, nullptr); |
| vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u); |
| endRenderPass(vkd, cmdBuffer); |
| vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &bufferBarrier, 0u, nullptr, 0u, nullptr); |
| endCommandBuffer(vkd, cmdBuffer); |
| submitCommandsAndWait(vkd, device, queue, cmdBuffer); |
| |
| // Verify intermediate results. |
| invalidateAlloc(vkd, device, bufferAlloc); |
| std::vector<deInt32> outputFlags (bufferCount, 0); |
| deMemcpy(outputFlags.data(), bufferData, static_cast<size_t>(bufferSize)); |
| |
| auto& log = m_context.getTestContext().getLog(); |
| log << tcu::TestLog::Message << "Verifying intermediate multisample copy results" << tcu::TestLog::EndMessage; |
| |
| const auto sampleCount = static_cast<deUint32>(m_params.samples); |
| |
| for (deUint32 x = 0u; x < fbWidth; ++x) |
| for (deUint32 y = 0u; y < fbHeight; ++y) |
| for (deUint32 s = 0u; s < sampleCount; ++s) |
| { |
| const auto index = (y * fbWidth + x) * sampleCount + s; |
| if (!outputFlags[index]) |
| { |
| std::ostringstream msg; |
| msg << "Intermediate verification failed for coordinates (" << x << ", " << y << ") sample " << s; |
| return tcu::TestStatus::fail(msg.str()); |
| } |
| } |
| |
| log << tcu::TestLog::Message << "Intermediate multisample copy verification passed" << tcu::TestLog::EndMessage; |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| void ResolveImageToImage::copyMSImageToMSImage (deUint32 copyArraySize) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| const tcu::TextureFormat srcTcuFormat = mapVkFormat(m_params.src.image.format); |
| std::vector<VkImageCopy> imageCopies; |
| std::vector<VkImageCopy2KHR> imageCopies2KHR; |
| |
| for (deUint32 layerNdx = 0; layerNdx < copyArraySize; ++layerNdx) |
| { |
| const VkImageSubresourceLayers sourceSubresourceLayers = |
| { |
| getAspectFlags(srcTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationSubresourceLayers = |
| { |
| getAspectFlags(srcTcuFormat), // VkImageAspectFlags aspectMask;//getAspectFlags(dstTcuFormat) |
| 0u, // deUint32 mipLevel; |
| layerNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy imageCopy = |
| { |
| sourceSubresourceLayers, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationSubresourceLayers, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| getExtent3D(m_params.src.image), // VkExtent3D extent; |
| }; |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| imageCopies.push_back(imageCopy); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| imageCopies2KHR.push_back(convertvkImageCopyTovkImageCopy2KHR(imageCopy)); |
| } |
| } |
| |
| const VkImageMemoryBarrier imageBarriers[] = |
| { |
| // source image |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; |
| m_params.src.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_multisampledImage.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(srcTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| getArraySize(m_params.src.image) // deUint32 arraySize; |
| } |
| }, |
| // destination image |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; |
| m_params.dst.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_multisampledCopyImage.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(srcTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| copyArraySize // deUint32 arraySize; |
| } |
| }, |
| }; |
| |
| const VkImageMemoryBarrier postImageBarriers = |
| // destination image |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| m_params.dst.image.operationLayout, // VkImageLayout oldLayout; |
| m_params.src.image.operationLayout, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| m_multisampledCopyImage.get(), // VkImage image; |
| { // VkImageSubresourceRange subresourceRange; |
| getAspectFlags(srcTcuFormat), // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 mipLevels; |
| 0u, // deUint32 baseArraySlice; |
| copyArraySize // deUint32 arraySize; |
| } |
| }; |
| |
| beginCommandBuffer(vk, *m_cmdBuffer); |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers); |
| |
| if (m_params.extensionUse == EXTENSION_USE_NONE) |
| { |
| vk.cmdCopyImage(*m_cmdBuffer, m_multisampledImage.get(), m_params.src.image.operationLayout, m_multisampledCopyImage.get(), m_params.dst.image.operationLayout, (deUint32)imageCopies.size(), imageCopies.data()); |
| } |
| else |
| { |
| DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2); |
| const VkCopyImageInfo2KHR copyImageInfo2KHR = |
| { |
| VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_multisampledImage.get(), // VkImage srcImage; |
| m_params.src.image.operationLayout, // VkImageLayout srcImageLayout; |
| m_multisampledCopyImage.get(), // VkImage dstImage; |
| m_params.dst.image.operationLayout, // VkImageLayout dstImageLayout; |
| (deUint32)imageCopies2KHR.size(), // uint32_t regionCount; |
| imageCopies2KHR.data() // const VkImageCopy2KHR* pRegions; |
| }; |
| |
| vk.cmdCopyImage2(*m_cmdBuffer, ©ImageInfo2KHR); |
| } |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarriers); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| |
| submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer); |
| } |
| |
| class ResolveImageToImageTestCase : public vkt::TestCase |
| { |
| public: |
| ResolveImageToImageTestCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams params, |
| const ResolveImageToImageOptions options = NO_OPTIONAL_OPERATION) |
| : vkt::TestCase (testCtx, name, description) |
| , m_params (params) |
| , m_options (options) |
| {} |
| |
| virtual void initPrograms (SourceCollections& programCollection) const; |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new ResolveImageToImage(context, m_params, m_options); |
| } |
| |
| virtual void checkSupport (Context& context) const |
| { |
| const VkSampleCountFlagBits rasterizationSamples = m_params.samples; |
| |
| if (!(context.getDeviceProperties().limits.framebufferColorSampleCounts & rasterizationSamples)) |
| throw tcu::NotSupportedError("Unsupported number of rasterization samples"); |
| |
| VkImageFormatProperties properties; |
| if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.src.image.format, |
| m_params.src.image.imageType, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) || |
| (context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(), |
| m_params.dst.image.format, |
| m_params.dst.image.imageType, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED)) |
| { |
| TCU_THROW(NotSupportedError, "Format not supported"); |
| } |
| |
| if ((m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2) && |
| (!context.isDeviceFunctionalitySupported("VK_KHR_copy_commands2"))) |
| { |
| TCU_THROW(NotSupportedError, "VK_KHR_copy_commands2 is not supported"); |
| } |
| } |
| |
| private: |
| TestParams m_params; |
| const ResolveImageToImageOptions m_options; |
| }; |
| |
| void ResolveImageToImageTestCase::initPrograms (SourceCollections& programCollection) const |
| { |
| programCollection.glslSources.add("vert") << glu::VertexSource( |
| "#version 310 es\n" |
| "layout (location = 0) in highp vec4 a_position;\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = a_position;\n" |
| "}\n"); |
| |
| |
| programCollection.glslSources.add("frag") << glu::FragmentSource( |
| "#version 310 es\n" |
| "layout (location = 0) out highp vec4 o_color;\n" |
| "void main()\n" |
| "{\n" |
| " o_color = vec4(0.0, 1.0, 0.0, 1.0);\n" |
| "}\n"); |
| |
| if (m_options == COPY_MS_IMAGE_TO_MS_IMAGE || m_options == COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE) |
| { |
| // The shader verifies all layers in the copied image are the same as the source image. |
| // This needs an image view per layer in the copied image. |
| // Set 0 contains the output buffer. |
| // Set 1 contains the input attachments. |
| |
| std::ostringstream verificationShader; |
| |
| verificationShader |
| << "#version 450\n" |
| << "\n" |
| << "layout (push_constant, std430) uniform PushConstants {\n" |
| << " int width;\n" |
| << " int height;\n" |
| << " int samples;\n" |
| << "};\n" |
| << "layout (set=0, binding=0) buffer VerificationResults {\n" |
| << " int verificationFlags[];\n" |
| << "};\n" |
| << "layout (input_attachment_index=0, set=1, binding=0) uniform subpassInputMS attachment0;\n" |
| ; |
| |
| const auto dstLayers = getArraySize(m_params.dst.image); |
| for (deUint32 layerNdx = 0u; layerNdx < dstLayers; ++layerNdx) |
| { |
| const auto i = layerNdx + 1u; |
| verificationShader << "layout (input_attachment_index=" << i << ", set=1, binding=" << i << ") uniform subpassInputMS attachment" << i << ";\n"; |
| } |
| |
| // Using a loop to iterate over each sample avoids the need for the sampleRateShading feature. The pipeline needs to be |
| // created with a single sample. |
| verificationShader |
| << "\n" |
| << "void main() {\n" |
| << " for (int sampleID = 0; sampleID < samples; ++sampleID) {\n" |
| << " vec4 orig = subpassLoad(attachment0, sampleID);\n" |
| ; |
| |
| for (deUint32 layerNdx = 0u; layerNdx < dstLayers; ++layerNdx) |
| { |
| const auto i = layerNdx + 1u; |
| verificationShader << " vec4 copy" << i << " = subpassLoad(attachment" << i << ", sampleID);\n"; |
| } |
| |
| std::ostringstream testCondition; |
| for (deUint32 layerNdx = 0u; layerNdx < dstLayers; ++layerNdx) |
| { |
| const auto i = layerNdx + 1u; |
| testCondition << (layerNdx == 0u ? "" : " && ") << "orig == copy" << i; |
| } |
| |
| verificationShader |
| << "\n" |
| << " ivec3 coords = ivec3(int(gl_FragCoord.x), int(gl_FragCoord.y), sampleID);\n" |
| << " int bufferPos = (coords.y * width + coords.x) * samples + coords.z;\n" |
| << "\n" |
| << " verificationFlags[bufferPos] = ((" << testCondition.str() << ") ? 1 : 0); \n" |
| << " }\n" |
| << "}\n" |
| ; |
| |
| programCollection.glslSources.add("verify") << glu::FragmentSource(verificationShader.str()); |
| } |
| } |
| |
| struct BufferOffsetParams |
| { |
| static constexpr deUint32 kMaxOffset = 8u; |
| |
| deUint32 srcOffset; |
| deUint32 dstOffset; |
| }; |
| |
| void checkZerosAt(const std::vector<deUint8>& bufferData, deUint32 from, deUint32 count) |
| { |
| constexpr deUint8 zero{0}; |
| for (deUint32 i = 0; i < count; ++i) |
| { |
| const auto& val = bufferData[from + i]; |
| if (val != zero) |
| { |
| std::ostringstream msg; |
| msg << "Unexpected non-zero byte found at position " << (from + i) << ": " << static_cast<int>(val); |
| TCU_FAIL(msg.str()); |
| } |
| } |
| } |
| |
| tcu::TestStatus bufferOffsetTest (Context& ctx, BufferOffsetParams params) |
| { |
| // Try to copy blocks of sizes 1 to kMaxOffset. Each copy region will use a block of kMaxOffset*2 bytes to take into account srcOffset and dstOffset. |
| constexpr auto kMaxOffset = BufferOffsetParams::kMaxOffset; |
| constexpr auto kBlockSize = kMaxOffset * 2u; |
| constexpr auto kBufferSize = kMaxOffset * kBlockSize; |
| |
| DE_ASSERT(params.srcOffset < kMaxOffset); |
| DE_ASSERT(params.dstOffset < kMaxOffset); |
| |
| const auto& vkd = ctx.getDeviceInterface(); |
| const auto device = ctx.getDevice(); |
| auto& alloc = ctx.getDefaultAllocator(); |
| const auto qIndex = ctx.getUniversalQueueFamilyIndex(); |
| const auto queue = ctx.getUniversalQueue(); |
| |
| const auto srcBufferInfo = makeBufferCreateInfo(kBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| const auto dstBufferInfo = makeBufferCreateInfo(kBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| BufferWithMemory srcBuffer (vkd, device, alloc, srcBufferInfo, MemoryRequirement::HostVisible); |
| BufferWithMemory dstBuffer (vkd, device, alloc, dstBufferInfo, MemoryRequirement::HostVisible); |
| auto& srcAlloc = srcBuffer.getAllocation(); |
| auto& dstAlloc = dstBuffer.getAllocation(); |
| |
| // Zero-out destination buffer. |
| deMemset(dstAlloc.getHostPtr(), 0, kBufferSize); |
| flushAlloc(vkd, device, dstAlloc); |
| |
| // Fill source buffer with nonzero bytes. |
| std::vector<deUint8> srcData; |
| srcData.reserve(kBufferSize); |
| for (deUint32 i = 0; i < kBufferSize; ++i) |
| srcData.push_back(static_cast<deUint8>(100u + i)); |
| deMemcpy(srcAlloc.getHostPtr(), srcData.data(), de::dataSize(srcData)); |
| flushAlloc(vkd, device, srcAlloc); |
| |
| // Copy regions. |
| std::vector<VkBufferCopy> copies; |
| copies.reserve(kMaxOffset); |
| for (deUint32 i = 0; i < kMaxOffset; ++i) |
| { |
| const auto blockStart = kBlockSize * i; |
| const auto copySize = i + 1u; |
| const auto bufferCopy = makeBufferCopy(params.srcOffset + blockStart, params.dstOffset + blockStart, copySize); |
| copies.push_back(bufferCopy); |
| } |
| |
| const auto cmdPool = makeCommandPool(vkd, device, qIndex); |
| const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| const auto cmdBuffer = cmdBufferPtr.get(); |
| |
| beginCommandBuffer(vkd, cmdBuffer); |
| vkd.cmdCopyBuffer(cmdBuffer, srcBuffer.get(), dstBuffer.get(), static_cast<deUint32>(copies.size()), copies.data()); |
| const auto barrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT); |
| vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &barrier, 0u, nullptr, 0u, nullptr); |
| endCommandBuffer(vkd, cmdBuffer); |
| submitCommandsAndWait(vkd, device, queue, cmdBuffer); |
| invalidateAlloc(vkd, device, dstAlloc); |
| |
| // Verify destination buffer data. |
| std::vector<deUint8> dstData(kBufferSize); |
| deMemcpy(dstData.data(), dstAlloc.getHostPtr(), de::dataSize(dstData)); |
| |
| for (deUint32 blockIdx = 0; blockIdx < kMaxOffset; ++blockIdx) |
| { |
| const auto blockStart = kBlockSize * blockIdx; |
| const auto copySize = blockIdx + 1u; |
| |
| // Verify no data has been written before dstOffset. |
| checkZerosAt(dstData, blockStart, params.dstOffset); |
| |
| // Verify copied block. |
| for (deUint32 i = 0; i < copySize; ++i) |
| { |
| const auto& dstVal = dstData[blockStart + params.dstOffset + i]; |
| const auto& srcVal = srcData[blockStart + params.srcOffset + i]; |
| if (dstVal != srcVal) |
| { |
| std::ostringstream msg; |
| msg << "Unexpected value found at position " << (blockStart + params.dstOffset + i) << ": expected " << static_cast<int>(srcVal) << " but found " << static_cast<int>(dstVal); |
| TCU_FAIL(msg.str()); |
| } |
| } |
| |
| // Verify no data has been written after copy block. |
| checkZerosAt(dstData, blockStart + params.dstOffset + copySize, kBlockSize - (params.dstOffset + copySize)); |
| } |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| std::string getSampleCountCaseName (VkSampleCountFlagBits sampleFlag) |
| { |
| return de::toLower(de::toString(getSampleCountFlagsStr(sampleFlag)).substr(16)); |
| } |
| |
| std::string getFormatCaseName (VkFormat format) |
| { |
| return de::toLower(de::toString(getFormatStr(format)).substr(10)); |
| } |
| |
| std::string getImageLayoutCaseName (VkImageLayout layout) |
| { |
| switch (layout) |
| { |
| case VK_IMAGE_LAYOUT_GENERAL: |
| return "general"; |
| case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: |
| case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: |
| return "optimal"; |
| default: |
| DE_ASSERT(false); |
| return ""; |
| } |
| } |
| |
| const deInt32 defaultSize = 64; |
| const deInt32 defaultHalfSize = defaultSize / 2; |
| const deInt32 defaultFourthSize = defaultSize / 4; |
| const deInt32 defaultSixteenthSize = defaultSize / 16; |
| const VkExtent3D defaultExtent = {defaultSize, defaultSize, 1}; |
| const VkExtent3D defaultHalfExtent = {defaultHalfSize, defaultHalfSize, 1}; |
| const VkExtent3D default1dExtent = {defaultSize, 1, 1}; |
| const VkExtent3D default3dExtent = {defaultFourthSize, defaultFourthSize, defaultFourthSize}; |
| |
| const VkImageSubresourceLayers defaultSourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u, // deUint32 layerCount; |
| }; |
| |
| void addImageToImageSimpleTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultExtent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| params.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "whole_image", "Whole image", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R32_UINT; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultExtent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| params.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "whole_image_diff_fromat", "Whole image with different format", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {defaultFourthSize, defaultFourthSize / 2, 0}, // VkOffset3D dstOffset; |
| {defaultFourthSize / 2, defaultFourthSize / 2, 1}, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| params.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "partial_image", "Partial image", params)); |
| } |
| |
| static const struct |
| { |
| std::string name; |
| vk::VkFormat format1; |
| vk::VkFormat format2; |
| } formats [] = |
| { |
| { "diff_format", vk::VK_FORMAT_R32_UINT, vk::VK_FORMAT_R8G8B8A8_UNORM }, |
| { "same_format", vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_FORMAT_R8G8B8A8_UNORM } |
| }; |
| static const struct |
| { |
| std::string name; |
| vk::VkBool32 clear; |
| } clears [] = |
| { |
| { "clear", VK_TRUE }, |
| { "noclear", VK_FALSE } |
| }; |
| static const struct |
| { |
| std::string name; |
| VkExtent3D extent; |
| } extents [] = |
| { |
| { "npot", {65u, 63u, 1u} }, |
| { "pot", {64u, 64u, 1u} } |
| }; |
| |
| for (const auto& format : formats) |
| { |
| for (const auto& clear : clears) |
| { |
| for (const auto& extent : extents) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = format.format1; |
| params.src.image.extent = extent.extent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = format.format2; |
| params.dst.image.extent = extent.extent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| params.clearDestination = clear.clear; |
| |
| { |
| VkImageCopy testCopy = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {34, 34, 0}, // VkOffset3D srcOffset; |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| {31, 29, 1} // VkExtent3D extent; |
| }; |
| |
| if (extent.name == "pot") |
| { |
| testCopy.srcOffset = { 16, 16, 0 }; |
| testCopy.extent = { 32, 32, 1 }; |
| } |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| params.regions.push_back(imageCopy); |
| } |
| |
| // Example test case name: "partial_image_npot_diff_format_clear" |
| const std::string testCaseName = "partial_image_" + extent.name + "_" + format.name + "_" + clear.name; |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, testCaseName, "", params)); |
| } |
| } |
| } |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_D32_SFLOAT; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_D32_SFLOAT; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_DEPTH_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {defaultFourthSize, defaultFourthSize / 2, 0}, // VkOffset3D dstOffset; |
| {defaultFourthSize / 2, defaultFourthSize / 2, 1}, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| params.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "depth", "With depth", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_S8_UINT; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_S8_UINT; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {defaultFourthSize, defaultFourthSize / 2, 0}, // VkOffset3D dstOffset; |
| {defaultFourthSize / 2, defaultFourthSize / 2, 1}, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| params.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "stencil", "With stencil", params)); |
| } |
| } |
| |
| struct CopyColorTestParams |
| { |
| TestParams params; |
| const VkFormat* compatibleFormats; |
| }; |
| |
| void addImageToImageAllFormatsColorSrcFormatDstFormatTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| const VkImageLayout copySrcLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| const VkImageLayout copyDstLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| |
| for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(copySrcLayouts); ++srcLayoutNdx) |
| { |
| params.src.image.operationLayout = copySrcLayouts[srcLayoutNdx]; |
| |
| for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(copyDstLayouts); ++dstLayoutNdx) |
| { |
| params.dst.image.operationLayout = copyDstLayouts[dstLayoutNdx]; |
| |
| const std::string testName = getImageLayoutCaseName(params.src.image.operationLayout) + "_" + |
| getImageLayoutCaseName(params.dst.image.operationLayout); |
| const std::string description = "From layout " + getImageLayoutCaseName(params.src.image.operationLayout) + |
| " to " + getImageLayoutCaseName(params.dst.image.operationLayout); |
| group->addChild(new CopyImageToImageTestCase(group->getTestContext(), testName, description, params)); |
| } |
| } |
| } |
| |
| bool isAllowedImageToImageAllFormatsColorSrcFormatTests(const CopyColorTestParams& testParams) |
| { |
| bool result = true; |
| |
| if (testParams.params.allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| DE_ASSERT(!dedicatedAllocationImageToImageFormatsToTestSet.empty()); |
| |
| result = |
| de::contains(dedicatedAllocationImageToImageFormatsToTestSet, testParams.params.dst.image.format) || |
| de::contains(dedicatedAllocationImageToImageFormatsToTestSet, testParams.params.src.image.format); |
| } |
| |
| return result; |
| } |
| |
| void addImageToImageAllFormatsColorSrcFormatTests (tcu::TestCaseGroup* group, CopyColorTestParams testParams) |
| { |
| // If testParams.compatibleFormats is nullptr, the destination format will be copied from the source format. |
| const VkFormat srcFormatOnly[2] = { testParams.params.src.image.format, VK_FORMAT_UNDEFINED }; |
| const VkFormat* formatList = (testParams.compatibleFormats ? testParams.compatibleFormats : srcFormatOnly); |
| |
| for (int dstFormatIndex = 0; formatList[dstFormatIndex] != VK_FORMAT_UNDEFINED; ++dstFormatIndex) |
| { |
| testParams.params.dst.image.format = formatList[dstFormatIndex]; |
| |
| const VkFormat srcFormat = testParams.params.src.image.format; |
| const VkFormat dstFormat = testParams.params.dst.image.format; |
| |
| if (!isSupportedByFramework(dstFormat) && !isCompressedFormat(dstFormat)) |
| continue; |
| |
| if (!isAllowedImageToImageAllFormatsColorSrcFormatTests(testParams)) |
| continue; |
| |
| if (isCompressedFormat(srcFormat) && isCompressedFormat(dstFormat)) |
| if ((getBlockWidth(srcFormat) != getBlockWidth(dstFormat)) || (getBlockHeight(srcFormat) != getBlockHeight(dstFormat))) |
| continue; |
| |
| const std::string description = "Copy to destination format " + getFormatCaseName(dstFormat); |
| addTestGroup(group, getFormatCaseName(dstFormat), description, addImageToImageAllFormatsColorSrcFormatDstFormatTests, testParams.params); |
| } |
| } |
| |
| const VkFormat compatibleFormats8Bit[] = |
| { |
| VK_FORMAT_R4G4_UNORM_PACK8, |
| VK_FORMAT_R8_UNORM, |
| VK_FORMAT_R8_SNORM, |
| VK_FORMAT_R8_USCALED, |
| VK_FORMAT_R8_SSCALED, |
| VK_FORMAT_R8_UINT, |
| VK_FORMAT_R8_SINT, |
| VK_FORMAT_R8_SRGB, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormats16Bit[] = |
| { |
| VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| VK_FORMAT_B4G4R4A4_UNORM_PACK16, |
| VK_FORMAT_R5G6B5_UNORM_PACK16, |
| VK_FORMAT_B5G6R5_UNORM_PACK16, |
| VK_FORMAT_R5G5B5A1_UNORM_PACK16, |
| VK_FORMAT_B5G5R5A1_UNORM_PACK16, |
| VK_FORMAT_A1R5G5B5_UNORM_PACK16, |
| VK_FORMAT_R8G8_UNORM, |
| VK_FORMAT_R8G8_SNORM, |
| VK_FORMAT_R8G8_USCALED, |
| VK_FORMAT_R8G8_SSCALED, |
| VK_FORMAT_R8G8_UINT, |
| VK_FORMAT_R8G8_SINT, |
| VK_FORMAT_R8G8_SRGB, |
| VK_FORMAT_R16_UNORM, |
| VK_FORMAT_R16_SNORM, |
| VK_FORMAT_R16_USCALED, |
| VK_FORMAT_R16_SSCALED, |
| VK_FORMAT_R16_UINT, |
| VK_FORMAT_R16_SINT, |
| VK_FORMAT_R16_SFLOAT, |
| VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, |
| VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormats24Bit[] = |
| { |
| VK_FORMAT_R8G8B8_UNORM, |
| VK_FORMAT_R8G8B8_SNORM, |
| VK_FORMAT_R8G8B8_USCALED, |
| VK_FORMAT_R8G8B8_SSCALED, |
| VK_FORMAT_R8G8B8_UINT, |
| VK_FORMAT_R8G8B8_SINT, |
| VK_FORMAT_R8G8B8_SRGB, |
| VK_FORMAT_B8G8R8_UNORM, |
| VK_FORMAT_B8G8R8_SNORM, |
| VK_FORMAT_B8G8R8_USCALED, |
| VK_FORMAT_B8G8R8_SSCALED, |
| VK_FORMAT_B8G8R8_UINT, |
| VK_FORMAT_B8G8R8_SINT, |
| VK_FORMAT_B8G8R8_SRGB, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormats32Bit[] = |
| { |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R8G8B8A8_SNORM, |
| VK_FORMAT_R8G8B8A8_USCALED, |
| VK_FORMAT_R8G8B8A8_SSCALED, |
| VK_FORMAT_R8G8B8A8_UINT, |
| VK_FORMAT_R8G8B8A8_SINT, |
| VK_FORMAT_R8G8B8A8_SRGB, |
| VK_FORMAT_B8G8R8A8_UNORM, |
| VK_FORMAT_B8G8R8A8_SNORM, |
| VK_FORMAT_B8G8R8A8_USCALED, |
| VK_FORMAT_B8G8R8A8_SSCALED, |
| VK_FORMAT_B8G8R8A8_UINT, |
| VK_FORMAT_B8G8R8A8_SINT, |
| VK_FORMAT_B8G8R8A8_SRGB, |
| VK_FORMAT_A8B8G8R8_UNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_SNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_USCALED_PACK32, |
| VK_FORMAT_A8B8G8R8_SSCALED_PACK32, |
| VK_FORMAT_A8B8G8R8_UINT_PACK32, |
| VK_FORMAT_A8B8G8R8_SINT_PACK32, |
| VK_FORMAT_A8B8G8R8_SRGB_PACK32, |
| VK_FORMAT_A2R10G10B10_UNORM_PACK32, |
| VK_FORMAT_A2R10G10B10_SNORM_PACK32, |
| VK_FORMAT_A2R10G10B10_USCALED_PACK32, |
| VK_FORMAT_A2R10G10B10_SSCALED_PACK32, |
| VK_FORMAT_A2R10G10B10_UINT_PACK32, |
| VK_FORMAT_A2R10G10B10_SINT_PACK32, |
| VK_FORMAT_A2B10G10R10_UNORM_PACK32, |
| VK_FORMAT_A2B10G10R10_SNORM_PACK32, |
| VK_FORMAT_A2B10G10R10_USCALED_PACK32, |
| VK_FORMAT_A2B10G10R10_SSCALED_PACK32, |
| VK_FORMAT_A2B10G10R10_UINT_PACK32, |
| VK_FORMAT_A2B10G10R10_SINT_PACK32, |
| VK_FORMAT_R16G16_UNORM, |
| VK_FORMAT_R16G16_SNORM, |
| VK_FORMAT_R16G16_USCALED, |
| VK_FORMAT_R16G16_SSCALED, |
| VK_FORMAT_R16G16_UINT, |
| VK_FORMAT_R16G16_SINT, |
| VK_FORMAT_R16G16_SFLOAT, |
| VK_FORMAT_R32_UINT, |
| VK_FORMAT_R32_SINT, |
| VK_FORMAT_R32_SFLOAT, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormats48Bit[] = |
| { |
| VK_FORMAT_R16G16B16_UNORM, |
| VK_FORMAT_R16G16B16_SNORM, |
| VK_FORMAT_R16G16B16_USCALED, |
| VK_FORMAT_R16G16B16_SSCALED, |
| VK_FORMAT_R16G16B16_UINT, |
| VK_FORMAT_R16G16B16_SINT, |
| VK_FORMAT_R16G16B16_SFLOAT, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormats64Bit[] = |
| { |
| VK_FORMAT_R16G16B16A16_UNORM, |
| VK_FORMAT_R16G16B16A16_SNORM, |
| VK_FORMAT_R16G16B16A16_USCALED, |
| VK_FORMAT_R16G16B16A16_SSCALED, |
| VK_FORMAT_R16G16B16A16_UINT, |
| VK_FORMAT_R16G16B16A16_SINT, |
| VK_FORMAT_R16G16B16A16_SFLOAT, |
| VK_FORMAT_R32G32_UINT, |
| VK_FORMAT_R32G32_SINT, |
| VK_FORMAT_R32G32_SFLOAT, |
| VK_FORMAT_R64_UINT, |
| VK_FORMAT_R64_SINT, |
| VK_FORMAT_R64_SFLOAT, |
| |
| VK_FORMAT_BC1_RGB_UNORM_BLOCK, |
| VK_FORMAT_BC1_RGB_SRGB_BLOCK, |
| VK_FORMAT_BC1_RGBA_UNORM_BLOCK, |
| VK_FORMAT_BC1_RGBA_SRGB_BLOCK, |
| VK_FORMAT_BC4_UNORM_BLOCK, |
| VK_FORMAT_BC4_SNORM_BLOCK, |
| |
| VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, |
| |
| VK_FORMAT_EAC_R11_UNORM_BLOCK, |
| VK_FORMAT_EAC_R11_SNORM_BLOCK, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormats96Bit[] = |
| { |
| VK_FORMAT_R32G32B32_UINT, |
| VK_FORMAT_R32G32B32_SINT, |
| VK_FORMAT_R32G32B32_SFLOAT, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormats128Bit[] = |
| { |
| VK_FORMAT_R32G32B32A32_UINT, |
| VK_FORMAT_R32G32B32A32_SINT, |
| VK_FORMAT_R32G32B32A32_SFLOAT, |
| VK_FORMAT_R64G64_UINT, |
| VK_FORMAT_R64G64_SINT, |
| VK_FORMAT_R64G64_SFLOAT, |
| |
| VK_FORMAT_BC2_UNORM_BLOCK, |
| VK_FORMAT_BC2_SRGB_BLOCK, |
| VK_FORMAT_BC3_UNORM_BLOCK, |
| VK_FORMAT_BC3_SRGB_BLOCK, |
| VK_FORMAT_BC5_UNORM_BLOCK, |
| VK_FORMAT_BC5_SNORM_BLOCK, |
| VK_FORMAT_BC6H_UFLOAT_BLOCK, |
| VK_FORMAT_BC6H_SFLOAT_BLOCK, |
| VK_FORMAT_BC7_UNORM_BLOCK, |
| VK_FORMAT_BC7_SRGB_BLOCK, |
| |
| VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, |
| |
| VK_FORMAT_EAC_R11G11_UNORM_BLOCK, |
| VK_FORMAT_EAC_R11G11_SNORM_BLOCK, |
| |
| VK_FORMAT_ASTC_4x4_UNORM_BLOCK, |
| VK_FORMAT_ASTC_4x4_SRGB_BLOCK, |
| VK_FORMAT_ASTC_5x4_UNORM_BLOCK, |
| VK_FORMAT_ASTC_5x4_SRGB_BLOCK, |
| VK_FORMAT_ASTC_5x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_5x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_6x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_6x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_6x6_UNORM_BLOCK, |
| VK_FORMAT_ASTC_6x6_SRGB_BLOCK, |
| VK_FORMAT_ASTC_8x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_8x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_8x6_UNORM_BLOCK, |
| VK_FORMAT_ASTC_8x6_SRGB_BLOCK, |
| VK_FORMAT_ASTC_8x8_UNORM_BLOCK, |
| VK_FORMAT_ASTC_8x8_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x6_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x6_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x8_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x8_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x10_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x10_SRGB_BLOCK, |
| VK_FORMAT_ASTC_12x10_UNORM_BLOCK, |
| VK_FORMAT_ASTC_12x10_SRGB_BLOCK, |
| VK_FORMAT_ASTC_12x12_UNORM_BLOCK, |
| VK_FORMAT_ASTC_12x12_SRGB_BLOCK, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormats192Bit[] = |
| { |
| VK_FORMAT_R64G64B64_UINT, |
| VK_FORMAT_R64G64B64_SINT, |
| VK_FORMAT_R64G64B64_SFLOAT, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormats256Bit[] = |
| { |
| VK_FORMAT_R64G64B64A64_UINT, |
| VK_FORMAT_R64G64B64A64_SINT, |
| VK_FORMAT_R64G64B64A64_SFLOAT, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| |
| const VkFormat* colorImageFormatsToTest[] = |
| { |
| compatibleFormats8Bit, |
| compatibleFormats16Bit, |
| compatibleFormats24Bit, |
| compatibleFormats32Bit, |
| compatibleFormats48Bit, |
| compatibleFormats64Bit, |
| compatibleFormats96Bit, |
| compatibleFormats128Bit, |
| compatibleFormats192Bit, |
| compatibleFormats256Bit |
| }; |
| |
| const VkFormat dedicatedAllocationImageToImageFormatsToTest[] = |
| { |
| // From compatibleFormats8Bit |
| VK_FORMAT_R4G4_UNORM_PACK8, |
| VK_FORMAT_R8_SRGB, |
| |
| // From compatibleFormats16Bit |
| VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| VK_FORMAT_R16_SFLOAT, |
| |
| // From compatibleFormats24Bit |
| VK_FORMAT_R8G8B8_UNORM, |
| VK_FORMAT_B8G8R8_SRGB, |
| |
| // From compatibleFormats32Bit |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R32_SFLOAT, |
| |
| // From compatibleFormats48Bit |
| VK_FORMAT_R16G16B16_UNORM, |
| VK_FORMAT_R16G16B16_SFLOAT, |
| |
| // From compatibleFormats64Bit |
| VK_FORMAT_R16G16B16A16_UNORM, |
| VK_FORMAT_R64_SFLOAT, |
| |
| // From compatibleFormats96Bit |
| VK_FORMAT_R32G32B32_UINT, |
| VK_FORMAT_R32G32B32_SFLOAT, |
| |
| // From compatibleFormats128Bit |
| VK_FORMAT_R32G32B32A32_UINT, |
| VK_FORMAT_R64G64_SFLOAT, |
| |
| // From compatibleFormats192Bit |
| VK_FORMAT_R64G64B64_UINT, |
| VK_FORMAT_R64G64B64_SFLOAT, |
| |
| // From compatibleFormats256Bit |
| VK_FORMAT_R64G64B64A64_UINT, |
| VK_FORMAT_R64G64B64A64_SFLOAT, |
| }; |
| |
| void addImageToImageAllFormatsColorTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| if (allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| const int numOfColorImageFormatsToTestFilter = DE_LENGTH_OF_ARRAY(colorImageFormatsToTest); |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTestFilter; ++compatibleFormatsIndex) |
| dedicatedAllocationImageToImageFormatsToTestSet.insert(dedicatedAllocationImageToImageFormatsToTest[compatibleFormatsIndex]); |
| } |
| |
| // 2D tests. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "2d", "2D copies")); |
| |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| for (deInt32 i = 0; i < defaultSize; i += defaultFourthSize) |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {i, defaultSize - i - defaultFourthSize, 0}, // VkOffset3D dstOffset; |
| {defaultFourthSize, defaultFourthSize, 1}, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| params.regions.push_back(imageCopy); |
| } |
| |
| const int numOfColorImageFormatsToTest = DE_LENGTH_OF_ARRAY(colorImageFormatsToTest); |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex) |
| { |
| const VkFormat* compatibleFormats = colorImageFormatsToTest[compatibleFormatsIndex]; |
| for (int srcFormatIndex = 0; compatibleFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex) |
| { |
| params.src.image.format = compatibleFormats[srcFormatIndex]; |
| if (!isSupportedByFramework(params.src.image.format) && !isCompressedFormat(params.src.image.format)) |
| continue; |
| |
| CopyColorTestParams testParams; |
| testParams.params = params; |
| testParams.compatibleFormats = compatibleFormats; |
| |
| const std::string testName = getFormatCaseName(params.src.image.format); |
| const std::string description = "Copy from source format " + getFormatCaseName(params.src.image.format); |
| addTestGroup(subGroup.get(), testName, description, addImageToImageAllFormatsColorSrcFormatTests, testParams); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| |
| // 1D tests. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "1d", "1D copies")); |
| |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_1D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_1D; |
| params.src.image.extent = default1dExtent; |
| params.dst.image.extent = default1dExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| for (deInt32 i = defaultFourthSize; i < defaultSize; i += defaultSize / 2) |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {i, 0, 0}, // VkOffset3D dstOffset; |
| {defaultFourthSize, 1, 1}, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| params.regions.push_back(imageCopy); |
| } |
| |
| const int numOfColorImageFormatsToTest = DE_LENGTH_OF_ARRAY(colorImageFormatsToTest); |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex) |
| { |
| const VkFormat* compatibleFormats = colorImageFormatsToTest[compatibleFormatsIndex]; |
| for (int srcFormatIndex = 0; compatibleFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex) |
| { |
| params.src.image.format = compatibleFormats[srcFormatIndex]; |
| if (!isSupportedByFramework(params.src.image.format) && !isCompressedFormat(params.src.image.format)) |
| continue; |
| |
| CopyColorTestParams testParams; |
| testParams.params = params; |
| testParams.compatibleFormats = nullptr; |
| |
| const std::string testName = getFormatCaseName(params.src.image.format); |
| const std::string description = "Copy from source format " + getFormatCaseName(params.src.image.format); |
| addTestGroup(subGroup.get(), testName, description, addImageToImageAllFormatsColorSrcFormatTests, testParams); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| |
| // 3D tests. Note we use smaller dimensions here for performance reasons. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "3d", "3D copies")); |
| |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_3D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_3D; |
| params.src.image.extent = default3dExtent; |
| params.dst.image.extent = default3dExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| for (deInt32 i = 0; i < defaultFourthSize; i += defaultSixteenthSize) |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {i, defaultFourthSize - i - defaultSixteenthSize, i}, // VkOffset3D dstOffset; |
| {defaultSixteenthSize, defaultSixteenthSize, defaultSixteenthSize}, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| params.regions.push_back(imageCopy); |
| } |
| |
| const int numOfColorImageFormatsToTest = DE_LENGTH_OF_ARRAY(colorImageFormatsToTest); |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex) |
| { |
| const VkFormat* compatibleFormats = colorImageFormatsToTest[compatibleFormatsIndex]; |
| for (int srcFormatIndex = 0; compatibleFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex) |
| { |
| params.src.image.format = compatibleFormats[srcFormatIndex]; |
| if (!isSupportedByFramework(params.src.image.format) && !isCompressedFormat(params.src.image.format)) |
| continue; |
| |
| CopyColorTestParams testParams; |
| testParams.params = params; |
| testParams.compatibleFormats = nullptr; |
| |
| const std::string testName = getFormatCaseName(params.src.image.format); |
| const std::string description = "Copy from source format " + getFormatCaseName(params.src.image.format); |
| addTestGroup(subGroup.get(), testName, description, addImageToImageAllFormatsColorSrcFormatTests, testParams); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| } |
| |
| void addImageToImageDimensionsTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| const VkFormat testFormats[][2] = |
| { |
| // From compatibleFormats8Bit |
| { |
| VK_FORMAT_R4G4_UNORM_PACK8, |
| VK_FORMAT_R8_SRGB |
| }, |
| // From compatibleFormats16Bit |
| { |
| VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| VK_FORMAT_R16_SFLOAT, |
| }, |
| // From compatibleFormats24Bit |
| { |
| VK_FORMAT_R8G8B8_UNORM, |
| VK_FORMAT_B8G8R8_SRGB |
| }, |
| // From compatibleFormats32Bit |
| { |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R32_SFLOAT |
| }, |
| // From compatibleFormats48Bit |
| { |
| VK_FORMAT_R16G16B16_UNORM, |
| VK_FORMAT_R16G16B16_SFLOAT |
| }, |
| // From compatibleFormats64Bit |
| { |
| VK_FORMAT_R16G16B16A16_UNORM, |
| VK_FORMAT_R64_SFLOAT |
| }, |
| // From compatibleFormats96Bit |
| { |
| VK_FORMAT_R32G32B32_UINT, |
| VK_FORMAT_R32G32B32_SFLOAT |
| }, |
| // From compatibleFormats128Bit |
| { |
| VK_FORMAT_R32G32B32A32_UINT, |
| VK_FORMAT_R64G64_SFLOAT |
| }, |
| // From compatibleFormats192Bit |
| { |
| VK_FORMAT_R64G64B64_UINT, |
| VK_FORMAT_R64G64B64_SFLOAT, |
| }, |
| // From compatibleFormats256Bit |
| { |
| VK_FORMAT_R64G64B64A64_UINT, |
| VK_FORMAT_R64G64B64A64_SFLOAT |
| } |
| }; |
| |
| const tcu::UVec2 imageDimensions[] = |
| { |
| // large pot x small pot |
| tcu::UVec2(4096, 4u), |
| tcu::UVec2(8192, 4u), |
| tcu::UVec2(16384, 4u), |
| tcu::UVec2(32768, 4u), |
| |
| // large pot x small npot |
| tcu::UVec2(4096, 6u), |
| tcu::UVec2(8192, 6u), |
| tcu::UVec2(16384, 6u), |
| tcu::UVec2(32768, 6u), |
| |
| // small pot x large pot |
| tcu::UVec2(4u, 4096), |
| tcu::UVec2(4u, 8192), |
| tcu::UVec2(4u, 16384), |
| tcu::UVec2(4u, 32768), |
| |
| // small npot x large pot |
| tcu::UVec2(6u, 4096), |
| tcu::UVec2(6u, 8192), |
| tcu::UVec2(6u, 16384), |
| tcu::UVec2(6u, 32768) |
| }; |
| |
| const VkImageLayout copySrcLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| |
| const VkImageLayout copyDstLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| |
| if (allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(testFormats); compatibleFormatsIndex++) |
| dedicatedAllocationImageToImageFormatsToTestSet.insert(dedicatedAllocationImageToImageFormatsToTest[compatibleFormatsIndex]); |
| } |
| |
| // Image dimensions |
| for (size_t dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(imageDimensions); dimensionNdx++) |
| { |
| CopyRegion copyRegion; |
| CopyColorTestParams testParams; |
| |
| const VkExtent3D extent = { imageDimensions[dimensionNdx].x(), imageDimensions[dimensionNdx].y(), 1 }; |
| |
| const VkImageCopy testCopy = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| extent, // VkExtent3D extent; |
| }; |
| |
| testParams.params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| testParams.params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| testParams.params.src.image.extent = extent; |
| |
| testParams.params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| testParams.params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| testParams.params.dst.image.extent = extent; |
| |
| copyRegion.imageCopy = testCopy; |
| testParams.params.allocationKind = allocationKind; |
| testParams.params.extensionUse = extensionUse; |
| |
| testParams.params.regions.push_back(copyRegion); |
| |
| const std::string dimensionStr = "src" + de::toString(testParams.params.src.image.extent.width) + "x" + de::toString(testParams.params.src.image.extent.height) |
| + "_dst" + de::toString(testParams.params.dst.image.extent.width) + "x" + de::toString(testParams.params.dst.image.extent.height); |
| tcu::TestCaseGroup* imageSizeGroup = new tcu::TestCaseGroup(testCtx, dimensionStr.c_str(), ("Image sizes " + dimensionStr).c_str()); |
| |
| // Compatible formats for copying |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(testFormats); compatibleFormatsIndex++) |
| { |
| const VkFormat* compatibleFormats = testFormats[compatibleFormatsIndex]; |
| |
| testParams.compatibleFormats = compatibleFormats; |
| |
| // Source image format |
| for (int srcFormatIndex = 0; srcFormatIndex < DE_LENGTH_OF_ARRAY(testFormats[compatibleFormatsIndex]); srcFormatIndex++) |
| { |
| testParams.params.src.image.format = testParams.compatibleFormats[srcFormatIndex]; |
| |
| if (!isSupportedByFramework(testParams.params.src.image.format) && !isCompressedFormat(testParams.params.src.image.format)) |
| continue; |
| |
| const std::string srcDescription = "Copy from source format " + getFormatCaseName(testParams.params.src.image.format); |
| tcu::TestCaseGroup* srcFormatGroup = new tcu::TestCaseGroup(testCtx, getFormatCaseName(testParams.params.src.image.format).c_str(), srcDescription.c_str()); |
| |
| // Destination image format |
| for (int dstFormatIndex = 0; dstFormatIndex < DE_LENGTH_OF_ARRAY(testFormats[compatibleFormatsIndex]); dstFormatIndex++) |
| { |
| testParams.params.dst.image.format = testParams.compatibleFormats[dstFormatIndex]; |
| |
| if (!isSupportedByFramework(testParams.params.dst.image.format) && !isCompressedFormat(testParams.params.dst.image.format)) |
| continue; |
| |
| if (!isAllowedImageToImageAllFormatsColorSrcFormatTests(testParams)) |
| continue; |
| |
| if (isCompressedFormat(testParams.params.src.image.format) && isCompressedFormat(testParams.params.dst.image.format)) |
| { |
| if ((getBlockWidth(testParams.params.src.image.format) != getBlockWidth(testParams.params.dst.image.format)) |
| || (getBlockHeight(testParams.params.src.image.format) != getBlockHeight(testParams.params.dst.image.format))) |
| continue; |
| } |
| |
| const std::string dstDescription = "Copy to destination format " + getFormatCaseName(testParams.params.dst.image.format); |
| tcu::TestCaseGroup* dstFormatGroup = new tcu::TestCaseGroup(testCtx, getFormatCaseName(testParams.params.dst.image.format).c_str(), dstDescription.c_str()); |
| |
| // Source/destionation image layouts |
| for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(copySrcLayouts); srcLayoutNdx++) |
| { |
| testParams.params.src.image.operationLayout = copySrcLayouts[srcLayoutNdx]; |
| |
| for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(copyDstLayouts); dstLayoutNdx++) |
| { |
| testParams.params.dst.image.operationLayout = copyDstLayouts[dstLayoutNdx]; |
| |
| const std::string testName = getImageLayoutCaseName(testParams.params.src.image.operationLayout) + "_" + getImageLayoutCaseName(testParams.params.dst.image.operationLayout); |
| const std::string description = "From layout " + getImageLayoutCaseName(testParams.params.src.image.operationLayout) + " to " + getImageLayoutCaseName(testParams.params.dst.image.operationLayout); |
| const TestParams params = testParams.params; |
| |
| dstFormatGroup->addChild(new CopyImageToImageTestCase(testCtx, testName, description, params)); |
| } |
| } |
| |
| srcFormatGroup->addChild(dstFormatGroup); |
| } |
| |
| imageSizeGroup->addChild(srcFormatGroup); |
| } |
| } |
| |
| group->addChild(imageSizeGroup); |
| } |
| } |
| |
| void addImageToImageAllFormatsDepthStencilFormatsTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| const VkImageLayout copySrcLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| const VkImageLayout copyDstLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| |
| for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(copySrcLayouts); ++srcLayoutNdx) |
| { |
| params.src.image.operationLayout = copySrcLayouts[srcLayoutNdx]; |
| for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(copyDstLayouts); ++dstLayoutNdx) |
| { |
| params.dst.image.operationLayout = copyDstLayouts[dstLayoutNdx]; |
| |
| const std::string testName = getImageLayoutCaseName(params.src.image.operationLayout) + "_" + |
| getImageLayoutCaseName(params.dst.image.operationLayout); |
| const std::string description = "From layout " + getImageLayoutCaseName(params.src.image.operationLayout) + |
| " to " + getImageLayoutCaseName(params.dst.image.operationLayout); |
| group->addChild(new CopyImageToImageTestCase(group->getTestContext(), testName, description, params)); |
| } |
| } |
| } |
| |
| void addImageToImageAllFormatsDepthStencilTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| const VkFormat depthAndStencilFormats[] = |
| { |
| VK_FORMAT_D16_UNORM, |
| VK_FORMAT_X8_D24_UNORM_PACK32, |
| VK_FORMAT_D32_SFLOAT, |
| VK_FORMAT_S8_UINT, |
| VK_FORMAT_D16_UNORM_S8_UINT, |
| VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_FORMAT_D32_SFLOAT_S8_UINT, |
| }; |
| |
| // 2D tests. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "2d", "2D copies")); |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(depthAndStencilFormats); ++compatibleFormatsIndex) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.format = depthAndStencilFormats[compatibleFormatsIndex]; |
| params.dst.image.format = params.src.image.format; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| params.separateDepthStencilLayouts = DE_FALSE; |
| |
| bool hasDepth = tcu::hasDepthComponent(mapVkFormat(params.src.image.format).order); |
| bool hasStencil = tcu::hasStencilComponent(mapVkFormat(params.src.image.format).order); |
| |
| const VkImageSubresourceLayers defaultDepthSourceLayer = { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, 1u }; |
| const VkImageSubresourceLayers defaultStencilSourceLayer = { VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u }; |
| const VkImageSubresourceLayers defaultDSSourceLayer = { VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u }; |
| |
| for (deInt32 i = 0; i < defaultSize; i += defaultFourthSize) |
| { |
| CopyRegion copyRegion; |
| const VkOffset3D srcOffset = {0, 0, 0}; |
| const VkOffset3D dstOffset = {i, defaultSize - i - defaultFourthSize, 0}; |
| const VkExtent3D extent = {defaultFourthSize, defaultFourthSize, 1}; |
| |
| if (hasDepth) |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultDepthSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| srcOffset, // VkOffset3D srcOffset; |
| defaultDepthSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| dstOffset, // VkOffset3D dstOffset; |
| extent, // VkExtent3D extent; |
| }; |
| |
| copyRegion.imageCopy = testCopy; |
| params.regions.push_back(copyRegion); |
| } |
| if (hasStencil) |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultStencilSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| srcOffset, // VkOffset3D srcOffset; |
| defaultStencilSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| dstOffset, // VkOffset3D dstOffset; |
| extent, // VkExtent3D extent; |
| }; |
| |
| copyRegion.imageCopy = testCopy; |
| params.regions.push_back(copyRegion); |
| } |
| } |
| |
| const std::string testName = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format); |
| const std::string description = "Copy from " + getFormatCaseName(params.src.image.format) + " to " + getFormatCaseName(params.dst.image.format); |
| addTestGroup(subGroup.get(), testName, description, addImageToImageAllFormatsDepthStencilFormatsTests, params); |
| |
| if (hasDepth && hasStencil) |
| { |
| params.separateDepthStencilLayouts = DE_TRUE; |
| const std::string testName2 = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format) + "_separate_layouts"; |
| const std::string description2 = "Copy from " + getFormatCaseName(params.src.image.format) + " to " + getFormatCaseName(params.dst.image.format) + " with separate depth/stencil layouts"; |
| addTestGroup(subGroup.get(), testName2, description2, addImageToImageAllFormatsDepthStencilFormatsTests, params); |
| |
| // DS Image copy |
| { |
| params.separateDepthStencilLayouts = DE_FALSE; |
| // Clear previous vkImageCopy elements |
| params.regions.clear(); |
| |
| for (deInt32 i = 0; i < defaultSize; i += defaultFourthSize) |
| { |
| CopyRegion copyRegion; |
| const VkOffset3D srcOffset = {0, 0, 0}; |
| const VkOffset3D dstOffset = {i, defaultSize - i - defaultFourthSize, 0}; |
| const VkExtent3D extent = {defaultFourthSize, defaultFourthSize, 1}; |
| |
| const VkImageCopy testCopy = |
| { |
| defaultDSSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| srcOffset, // VkOffset3D srcOffset; |
| defaultDSSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| dstOffset, // VkOffset3D dstOffset; |
| extent, // VkExtent3D extent; |
| }; |
| |
| copyRegion.imageCopy = testCopy; |
| params.regions.push_back(copyRegion); |
| } |
| |
| const std::string testName3 = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format) + "_depth_stencil_aspects"; |
| const std::string description3 = "Copy both depth and stencil aspects from " + getFormatCaseName(params.src.image.format) + " to " + getFormatCaseName(params.dst.image.format); |
| addTestGroup(subGroup.get(), testName3, description3, addImageToImageAllFormatsDepthStencilFormatsTests, params); |
| } |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| |
| // 1D tests. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "1d", "1D copies")); |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(depthAndStencilFormats); ++compatibleFormatsIndex) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_1D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_1D; |
| params.src.image.extent = default1dExtent; |
| params.dst.image.extent = default1dExtent; |
| params.src.image.format = depthAndStencilFormats[compatibleFormatsIndex]; |
| params.dst.image.format = params.src.image.format; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| bool hasDepth = tcu::hasDepthComponent(mapVkFormat(params.src.image.format).order); |
| bool hasStencil = tcu::hasStencilComponent(mapVkFormat(params.src.image.format).order); |
| |
| const VkImageSubresourceLayers defaultDepthSourceLayer = { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, 1u }; |
| const VkImageSubresourceLayers defaultStencilSourceLayer = { VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u }; |
| |
| for (deInt32 i = defaultFourthSize; i < defaultSize; i += defaultSize / 2) |
| { |
| CopyRegion copyRegion; |
| const VkOffset3D srcOffset = {0, 0, 0}; |
| const VkOffset3D dstOffset = {i, 0, 0}; |
| const VkExtent3D extent = {defaultFourthSize, 1, 1}; |
| |
| if (hasDepth) |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultDepthSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| srcOffset, // VkOffset3D srcOffset; |
| defaultDepthSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| dstOffset, // VkOffset3D dstOffset; |
| extent, // VkExtent3D extent; |
| }; |
| |
| copyRegion.imageCopy = testCopy; |
| params.regions.push_back(copyRegion); |
| } |
| if (hasStencil) |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultStencilSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| srcOffset, // VkOffset3D srcOffset; |
| defaultStencilSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| dstOffset, // VkOffset3D dstOffset; |
| extent, // VkExtent3D extent; |
| }; |
| |
| copyRegion.imageCopy = testCopy; |
| params.regions.push_back(copyRegion); |
| } |
| } |
| |
| const std::string testName = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format); |
| const std::string description = "Copy from " + getFormatCaseName(params.src.image.format) + " to " + getFormatCaseName(params.dst.image.format); |
| addTestGroup(subGroup.get(), testName, description, addImageToImageAllFormatsDepthStencilFormatsTests, params); |
| |
| if (hasDepth && hasStencil) |
| { |
| params.separateDepthStencilLayouts = DE_TRUE; |
| const std::string testName2 = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format) + "_separate_layouts"; |
| const std::string description2 = "Copy from " + getFormatCaseName(params.src.image.format) + " to " + getFormatCaseName(params.dst.image.format) + " with separate depth/stencil layouts"; |
| addTestGroup(subGroup.get(), testName2, description2, addImageToImageAllFormatsDepthStencilFormatsTests, params); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| |
| // 3D tests. Note we use smaller dimensions here for performance reasons. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "3d", "3D copies")); |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(depthAndStencilFormats); ++compatibleFormatsIndex) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_3D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_3D; |
| params.src.image.extent = default3dExtent; |
| params.dst.image.extent = default3dExtent; |
| params.src.image.format = depthAndStencilFormats[compatibleFormatsIndex]; |
| params.dst.image.format = params.src.image.format; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| bool hasDepth = tcu::hasDepthComponent(mapVkFormat(params.src.image.format).order); |
| bool hasStencil = tcu::hasStencilComponent(mapVkFormat(params.src.image.format).order); |
| |
| const VkImageSubresourceLayers defaultDepthSourceLayer = { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, 1u }; |
| const VkImageSubresourceLayers defaultStencilSourceLayer = { VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u }; |
| |
| for (deInt32 i = 0; i < defaultFourthSize; i += defaultSixteenthSize) |
| { |
| CopyRegion copyRegion; |
| const VkOffset3D srcOffset = {0, 0, 0}; |
| const VkOffset3D dstOffset = {i, defaultFourthSize - i - defaultSixteenthSize, i}; |
| const VkExtent3D extent = {defaultSixteenthSize, defaultSixteenthSize, defaultSixteenthSize}; |
| |
| if (hasDepth) |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultDepthSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| srcOffset, // VkOffset3D srcOffset; |
| defaultDepthSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| dstOffset, // VkOffset3D dstOffset; |
| extent, // VkExtent3D extent; |
| }; |
| |
| copyRegion.imageCopy = testCopy; |
| params.regions.push_back(copyRegion); |
| } |
| if (hasStencil) |
| { |
| const VkImageCopy testCopy = |
| { |
| defaultStencilSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| srcOffset, // VkOffset3D srcOffset; |
| defaultStencilSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| dstOffset, // VkOffset3D dstOffset; |
| extent, // VkExtent3D extent; |
| }; |
| |
| copyRegion.imageCopy = testCopy; |
| params.regions.push_back(copyRegion); |
| } |
| } |
| |
| const std::string testName = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format); |
| const std::string description = "Copy from " + getFormatCaseName(params.src.image.format) + " to " + getFormatCaseName(params.dst.image.format); |
| addTestGroup(subGroup.get(), testName, description, addImageToImageAllFormatsDepthStencilFormatsTests, params); |
| |
| if (hasDepth && hasStencil) |
| { |
| params.separateDepthStencilLayouts = DE_TRUE; |
| const std::string testName2 = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format) + "_separate_layouts"; |
| const std::string description2 = "Copy from " + getFormatCaseName(params.src.image.format) + " to " + getFormatCaseName(params.dst.image.format) + " with separate depth/stencil layouts"; |
| addTestGroup(subGroup.get(), testName2, description2, addImageToImageAllFormatsDepthStencilFormatsTests, params); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| } |
| |
| void addImageToImageAllFormatsTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| addTestGroup(group, "color", "Copy image to image with color formats", addImageToImageAllFormatsColorTests, allocationKind, extensionUse); |
| addTestGroup(group, "depth_stencil", "Copy image to image with depth/stencil formats", addImageToImageAllFormatsDepthStencilTests, allocationKind, extensionUse); |
| } |
| |
| void addImageToImage3dImagesTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| { |
| TestParams params3DTo2D; |
| const deUint32 slicesLayers = 16u; |
| params3DTo2D.src.image.imageType = VK_IMAGE_TYPE_3D; |
| params3DTo2D.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params3DTo2D.src.image.extent = defaultHalfExtent; |
| params3DTo2D.src.image.extent.depth = slicesLayers; |
| params3DTo2D.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params3DTo2D.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params3DTo2D.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params3DTo2D.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params3DTo2D.dst.image.extent = defaultHalfExtent; |
| params3DTo2D.dst.image.extent.depth = slicesLayers; |
| params3DTo2D.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params3DTo2D.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params3DTo2D.allocationKind = allocationKind; |
| params3DTo2D.extensionUse = extensionUse; |
| |
| for (deUint32 slicesLayersNdx = 0; slicesLayersNdx < slicesLayers; ++slicesLayersNdx) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| slicesLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, (deInt32)slicesLayersNdx}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultHalfExtent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| params3DTo2D.regions.push_back(imageCopy); |
| } |
| group->addChild(new CopyImageToImageTestCase(testCtx, "3d_to_2d_by_slices", "copy 2d layers to 3d slices one by one", params3DTo2D)); |
| } |
| |
| { |
| TestParams params2DTo3D; |
| const deUint32 slicesLayers = 16u; |
| params2DTo3D.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params2DTo3D.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params2DTo3D.src.image.extent = defaultHalfExtent; |
| params2DTo3D.src.image.extent.depth = slicesLayers; |
| params2DTo3D.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params2DTo3D.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params2DTo3D.dst.image.imageType = VK_IMAGE_TYPE_3D; |
| params2DTo3D.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params2DTo3D.dst.image.extent = defaultHalfExtent; |
| params2DTo3D.dst.image.extent.depth = slicesLayers; |
| params2DTo3D.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params2DTo3D.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params2DTo3D.allocationKind = allocationKind; |
| params2DTo3D.extensionUse = extensionUse; |
| |
| for (deUint32 slicesLayersNdx = 0; slicesLayersNdx < slicesLayers; ++slicesLayersNdx) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| slicesLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, (deInt32)slicesLayersNdx}, // VkOffset3D dstOffset; |
| defaultHalfExtent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| params2DTo3D.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "2d_to_3d_by_layers", "copy 3d slices to 2d layers one by one", params2DTo3D)); |
| } |
| |
| { |
| TestParams params3DTo2D; |
| const deUint32 slicesLayers = 16u; |
| params3DTo2D.src.image.imageType = VK_IMAGE_TYPE_3D; |
| params3DTo2D.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params3DTo2D.src.image.extent = defaultHalfExtent; |
| params3DTo2D.src.image.extent.depth = slicesLayers; |
| params3DTo2D.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params3DTo2D.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params3DTo2D.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params3DTo2D.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params3DTo2D.dst.image.extent = defaultHalfExtent; |
| params3DTo2D.dst.image.extent.depth = slicesLayers; |
| params3DTo2D.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params3DTo2D.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params3DTo2D.allocationKind = allocationKind; |
| params3DTo2D.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0, // deUint32 baseArrayLayer; |
| slicesLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| params3DTo2D.src.image.extent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| params3DTo2D.regions.push_back(imageCopy); |
| } |
| group->addChild(new CopyImageToImageTestCase(testCtx, "3d_to_2d_whole", "copy 3d slices to 2d layers all at once", params3DTo2D)); |
| } |
| |
| { |
| TestParams params2DTo3D; |
| const deUint32 slicesLayers = 16u; |
| params2DTo3D.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params2DTo3D.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params2DTo3D.src.image.extent = defaultHalfExtent; |
| params2DTo3D.src.image.extent.depth = slicesLayers; |
| params2DTo3D.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params2DTo3D.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params2DTo3D.dst.image.imageType = VK_IMAGE_TYPE_3D; |
| params2DTo3D.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params2DTo3D.dst.image.extent = defaultHalfExtent; |
| params2DTo3D.dst.image.extent.depth = slicesLayers; |
| params2DTo3D.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params2DTo3D.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params2DTo3D.allocationKind = allocationKind; |
| params2DTo3D.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| slicesLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| params2DTo3D.src.image.extent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| params2DTo3D.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "2d_to_3d_whole", "copy 2d layers to 3d slices all at once", params2DTo3D)); |
| } |
| |
| { |
| TestParams params3DTo2D; |
| const deUint32 slicesLayers = 16u; |
| params3DTo2D.src.image.imageType = VK_IMAGE_TYPE_3D; |
| params3DTo2D.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params3DTo2D.src.image.extent = defaultHalfExtent; |
| params3DTo2D.src.image.extent.depth = slicesLayers; |
| params3DTo2D.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params3DTo2D.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params3DTo2D.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params3DTo2D.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params3DTo2D.dst.image.extent = defaultHalfExtent; |
| params3DTo2D.dst.image.extent.depth = slicesLayers; |
| params3DTo2D.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params3DTo2D.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params3DTo2D.allocationKind = allocationKind; |
| params3DTo2D.extensionUse = extensionUse; |
| |
| const deUint32 regionWidth = defaultHalfExtent.width / slicesLayers -1; |
| const deUint32 regionHeight = defaultHalfExtent.height / slicesLayers -1 ; |
| |
| for (deUint32 slicesLayersNdx = 0; slicesLayersNdx < slicesLayers; ++slicesLayersNdx) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| slicesLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, (deInt32)(regionHeight*slicesLayersNdx), (deInt32)slicesLayersNdx}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {(deInt32)(regionWidth*slicesLayersNdx), 0, 0}, // VkOffset3D dstOffset; |
| { |
| (defaultHalfExtent.width - regionWidth*slicesLayersNdx), |
| (defaultHalfExtent.height - regionHeight*slicesLayersNdx), |
| 1 |
| } // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| params3DTo2D.regions.push_back(imageCopy); |
| } |
| group->addChild(new CopyImageToImageTestCase(testCtx, "3d_to_2d_regions", "copy 3d slices regions to 2d layers", params3DTo2D)); |
| } |
| |
| { |
| TestParams params2DTo3D; |
| const deUint32 slicesLayers = 16u; |
| params2DTo3D.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params2DTo3D.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params2DTo3D.src.image.extent = defaultHalfExtent; |
| params2DTo3D.src.image.extent.depth = slicesLayers; |
| params2DTo3D.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params2DTo3D.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params2DTo3D.dst.image.imageType = VK_IMAGE_TYPE_3D; |
| params2DTo3D.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params2DTo3D.dst.image.extent = defaultHalfExtent; |
| params2DTo3D.dst.image.extent.depth = slicesLayers; |
| params2DTo3D.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params2DTo3D.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params2DTo3D.allocationKind = allocationKind; |
| params2DTo3D.extensionUse = extensionUse; |
| |
| const deUint32 regionWidth = defaultHalfExtent.width / slicesLayers -1; |
| const deUint32 regionHeight = defaultHalfExtent.height / slicesLayers -1 ; |
| |
| for (deUint32 slicesLayersNdx = 0; slicesLayersNdx < slicesLayers; ++slicesLayersNdx) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| slicesLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {(deInt32)(regionWidth*slicesLayersNdx), 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, (deInt32)(regionHeight*slicesLayersNdx), (deInt32)(slicesLayersNdx)}, // VkOffset3D dstOffset; |
| { |
| defaultHalfExtent.width - regionWidth*slicesLayersNdx, |
| defaultHalfExtent.height - regionHeight*slicesLayersNdx, |
| 1 |
| } // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| params2DTo3D.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "2d_to_3d_regions", "copy 2d layers regions to 3d slices", params2DTo3D)); |
| } |
| } |
| |
| void addImageToImageCubeTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| { |
| TestParams paramsCubeToArray; |
| const deUint32 arrayLayers = 6u; |
| paramsCubeToArray.src.image.createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; |
| paramsCubeToArray.src.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsCubeToArray.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsCubeToArray.src.image.extent = defaultHalfExtent; |
| paramsCubeToArray.src.image.extent.depth = arrayLayers; |
| paramsCubeToArray.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsCubeToArray.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| paramsCubeToArray.dst.image.createFlags = 0; |
| paramsCubeToArray.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsCubeToArray.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsCubeToArray.dst.image.extent = defaultHalfExtent; |
| paramsCubeToArray.dst.image.extent.depth = arrayLayers; |
| paramsCubeToArray.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsCubeToArray.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| paramsCubeToArray.allocationKind = allocationKind; |
| paramsCubeToArray.extensionUse = extensionUse; |
| |
| for (deUint32 arrayLayersNdx = 0; arrayLayersNdx < arrayLayers; ++arrayLayersNdx) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultHalfExtent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| paramsCubeToArray.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "cube_to_array_layers", "copy cube compatible image to 2d layers layer by layer", paramsCubeToArray)); |
| } |
| |
| { |
| TestParams paramsCubeToArray; |
| const deUint32 arrayLayers = 6u; |
| paramsCubeToArray.src.image.createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; |
| paramsCubeToArray.src.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsCubeToArray.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsCubeToArray.src.image.extent = defaultHalfExtent; |
| paramsCubeToArray.src.image.extent.depth = arrayLayers; |
| paramsCubeToArray.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsCubeToArray.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| paramsCubeToArray.dst.image.createFlags = 0; |
| paramsCubeToArray.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsCubeToArray.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsCubeToArray.dst.image.extent = defaultHalfExtent; |
| paramsCubeToArray.dst.image.extent.depth = arrayLayers; |
| paramsCubeToArray.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsCubeToArray.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| paramsCubeToArray.allocationKind = allocationKind; |
| paramsCubeToArray.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultHalfExtent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| paramsCubeToArray.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "cube_to_array_whole", "copy cube compatible image to 2d layers all at once", paramsCubeToArray)); |
| } |
| |
| { |
| TestParams paramsArrayToCube; |
| const deUint32 arrayLayers = 6u; |
| paramsArrayToCube.src.image.createFlags = 0; |
| paramsArrayToCube.src.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToCube.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsArrayToCube.src.image.extent = defaultHalfExtent; |
| paramsArrayToCube.src.image.extent.depth = arrayLayers; |
| paramsArrayToCube.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToCube.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| paramsArrayToCube.dst.image.createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; |
| paramsArrayToCube.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToCube.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsArrayToCube.dst.image.extent = defaultHalfExtent; |
| paramsArrayToCube.dst.image.extent.depth = arrayLayers; |
| paramsArrayToCube.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToCube.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| paramsArrayToCube.allocationKind = allocationKind; |
| paramsArrayToCube.extensionUse = extensionUse; |
| |
| for (deUint32 arrayLayersNdx = 0; arrayLayersNdx < arrayLayers; ++arrayLayersNdx) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultHalfExtent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| paramsArrayToCube.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "array_to_cube_layers", "copy 2d layers to cube compatible image layer by layer", paramsArrayToCube)); |
| } |
| |
| { |
| TestParams paramsArrayToCube; |
| const deUint32 arrayLayers = 6u; |
| paramsArrayToCube.src.image.createFlags = 0; |
| paramsArrayToCube.src.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToCube.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsArrayToCube.src.image.extent = defaultHalfExtent; |
| paramsArrayToCube.src.image.extent.depth = arrayLayers; |
| paramsArrayToCube.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToCube.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| paramsArrayToCube.dst.image.createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; |
| paramsArrayToCube.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToCube.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsArrayToCube.dst.image.extent = defaultHalfExtent; |
| paramsArrayToCube.dst.image.extent.depth = arrayLayers; |
| paramsArrayToCube.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToCube.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| paramsArrayToCube.allocationKind = allocationKind; |
| paramsArrayToCube.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultHalfExtent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| paramsArrayToCube.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "array_to_cube_whole", "copy 2d layers to cube compatible image all at once", paramsArrayToCube)); |
| } |
| |
| { |
| TestParams paramsCubeToArray; |
| const deUint32 arrayLayers = 6u; |
| paramsCubeToArray.src.image.createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; |
| paramsCubeToArray.src.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsCubeToArray.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsCubeToArray.src.image.extent = defaultHalfExtent; |
| paramsCubeToArray.src.image.extent.depth = arrayLayers; |
| paramsCubeToArray.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsCubeToArray.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| paramsCubeToArray.dst.image.createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; |
| paramsCubeToArray.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsCubeToArray.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsCubeToArray.dst.image.extent = defaultHalfExtent; |
| paramsCubeToArray.dst.image.extent.depth = arrayLayers; |
| paramsCubeToArray.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsCubeToArray.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| paramsCubeToArray.allocationKind = allocationKind; |
| paramsCubeToArray.extensionUse = extensionUse; |
| |
| for (deUint32 arrayLayersNdx = 0; arrayLayersNdx < arrayLayers; ++arrayLayersNdx) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultHalfExtent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| paramsCubeToArray.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "cube_to_cube_layers", "copy cube compatible image to cube compatible image layer by layer", paramsCubeToArray)); |
| } |
| |
| { |
| TestParams paramsCubeToCube; |
| const deUint32 arrayLayers = 6u; |
| paramsCubeToCube.src.image.createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; |
| paramsCubeToCube.src.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsCubeToCube.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsCubeToCube.src.image.extent = defaultHalfExtent; |
| paramsCubeToCube.src.image.extent.depth = arrayLayers; |
| paramsCubeToCube.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsCubeToCube.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| paramsCubeToCube.dst.image.createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; |
| paramsCubeToCube.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsCubeToCube.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsCubeToCube.dst.image.extent = defaultHalfExtent; |
| paramsCubeToCube.dst.image.extent.depth = arrayLayers; |
| paramsCubeToCube.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsCubeToCube.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| paramsCubeToCube.allocationKind = allocationKind; |
| paramsCubeToCube.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultHalfExtent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| paramsCubeToCube.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "cube_to_cube_whole", "copy cube compatible image to cube compatible image all at once", paramsCubeToCube)); |
| } |
| } |
| |
| void addImageToImageArrayTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| { |
| TestParams paramsArrayToArray; |
| const deUint32 arrayLayers = 16u; |
| paramsArrayToArray.src.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToArray.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsArrayToArray.src.image.extent = defaultHalfExtent; |
| paramsArrayToArray.src.image.extent.depth = arrayLayers; |
| paramsArrayToArray.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToArray.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| paramsArrayToArray.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToArray.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsArrayToArray.dst.image.extent = defaultHalfExtent; |
| paramsArrayToArray.dst.image.extent.depth = arrayLayers; |
| paramsArrayToArray.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToArray.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| paramsArrayToArray.allocationKind = allocationKind; |
| paramsArrayToArray.extensionUse = extensionUse; |
| |
| for (deUint32 arrayLayersNdx = 0; arrayLayersNdx < arrayLayers; ++arrayLayersNdx) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayersNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultHalfExtent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| paramsArrayToArray.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "array_to_array_layers", "copy 2d array image to 2d array image layer by layer", paramsArrayToArray)); |
| } |
| |
| { |
| TestParams paramsArrayToArray; |
| const deUint32 arrayLayers = 16u; |
| paramsArrayToArray.src.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToArray.src.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsArrayToArray.src.image.extent = defaultHalfExtent; |
| paramsArrayToArray.src.image.extent.depth = arrayLayers; |
| paramsArrayToArray.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToArray.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| paramsArrayToArray.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToArray.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| paramsArrayToArray.dst.image.extent = defaultHalfExtent; |
| paramsArrayToArray.dst.image.extent.depth = arrayLayers; |
| paramsArrayToArray.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToArray.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| paramsArrayToArray.allocationKind = allocationKind; |
| paramsArrayToArray.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultHalfExtent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| paramsArrayToArray.regions.push_back(imageCopy); |
| } |
| |
| group->addChild(new CopyImageToImageTestCase(testCtx, "array_to_array_whole", "copy 2d array image to 2d array image all at once", paramsArrayToArray)); |
| } |
| |
| { |
| TestParams paramsArrayToArray; |
| const deUint32 arrayLayers = 16u; |
| paramsArrayToArray.src.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToArray.src.image.extent = defaultHalfExtent; |
| paramsArrayToArray.src.image.extent.depth = arrayLayers; |
| paramsArrayToArray.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToArray.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| paramsArrayToArray.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| paramsArrayToArray.dst.image.extent = defaultHalfExtent; |
| paramsArrayToArray.dst.image.extent.depth = arrayLayers; |
| paramsArrayToArray.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| paramsArrayToArray.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| paramsArrayToArray.allocationKind = allocationKind; |
| paramsArrayToArray.extensionUse = extensionUse; |
| paramsArrayToArray.mipLevels = deLog2Floor32(deMinu32(defaultHalfExtent.width, defaultHalfExtent.height)) + 1u; |
| |
| for (deUint32 mipLevelNdx = 0u; mipLevelNdx < paramsArrayToArray.mipLevels; mipLevelNdx++) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| mipLevelNdx, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkImageSubresourceLayers destinationLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| mipLevelNdx, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| arrayLayers // deUint32 layerCount; |
| }; |
| |
| const VkExtent3D extent = |
| { |
| (deUint32)deMax(defaultHalfExtent.width >> mipLevelNdx, 1), // deUint32 width; |
| (deUint32)deMax(defaultHalfExtent.height >> mipLevelNdx, 1), // deUint32 height; |
| 1u, // deUint32 depth; |
| }; |
| |
| const VkImageCopy testCopy = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| destinationLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| extent // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageCopy; |
| imageCopy.imageCopy = testCopy; |
| |
| paramsArrayToArray.regions.push_back(imageCopy); |
| } |
| |
| VkFormat imageFormats [] = { VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D16_UNORM, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_S8_UINT}; |
| |
| for (deUint32 imageFormatsNdx = 0; imageFormatsNdx < DE_LENGTH_OF_ARRAY(imageFormats); imageFormatsNdx++) |
| { |
| paramsArrayToArray.src.image.format = imageFormats[imageFormatsNdx]; |
| paramsArrayToArray.dst.image.format = imageFormats[imageFormatsNdx]; |
| for (deUint32 regionNdx = 0u; regionNdx < paramsArrayToArray.regions.size(); regionNdx++) |
| { |
| paramsArrayToArray.regions[regionNdx].imageCopy.srcSubresource.aspectMask = getImageAspectFlags(mapVkFormat(imageFormats[imageFormatsNdx])); |
| paramsArrayToArray.regions[regionNdx].imageCopy.dstSubresource.aspectMask = getImageAspectFlags(mapVkFormat(imageFormats[imageFormatsNdx])); |
| } |
| std::ostringstream testName; |
| const std::string formatName = getFormatName(imageFormats[imageFormatsNdx]); |
| testName << "array_to_array_whole_mipmap_" << de::toLower(formatName.substr(10)); |
| group->addChild(new CopyImageToImageMipmapTestCase(testCtx, testName.str(), "copy 2d array mipmap image to 2d array mipmap image all at once", paramsArrayToArray)); |
| } |
| } |
| } |
| |
| void addImageToImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| addTestGroup(group, "simple_tests", "Copy from image to image simple tests", addImageToImageSimpleTests, allocationKind, extensionUse); |
| addTestGroup(group, "all_formats", "Copy from image to image with all compatible formats", addImageToImageAllFormatsTests, allocationKind, extensionUse); |
| addTestGroup(group, "3d_images", "Coping operations on 3d images", addImageToImage3dImagesTests, allocationKind, extensionUse); |
| addTestGroup(group, "dimensions", "Copying operations on different image dimensions", addImageToImageDimensionsTests, allocationKind, extensionUse); |
| addTestGroup(group, "cube", "Coping operations on cube compatible images", addImageToImageCubeTests, allocationKind, extensionUse); |
| addTestGroup(group, "array", "Copying operations on array of images", addImageToImageArrayTests, allocationKind, extensionUse); |
| } |
| |
| void addImageToBufferTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.buffer.size = defaultSize * defaultSize; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {0, 0, 0}, // VkOffset3D imageOffset; |
| defaultExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyImageToBufferTestCase(testCtx, "whole", "Copy from image to buffer", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.buffer.size = defaultSize * defaultSize; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| defaultSize * defaultHalfSize, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyImageToBufferTestCase(testCtx, "buffer_offset", "Copy from image to buffer with buffer offset", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.buffer.size = defaultSize * defaultSize; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| defaultSize * defaultHalfSize + 1u, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyImageToBufferTestCase(testCtx, "buffer_offset_relaxed", "Copy from image to buffer with buffer offset not a multiple of 4", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.buffer.size = defaultSize * defaultSize; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const int pixelSize = tcu::getPixelSize(mapVkFormat(params.src.image.format)); |
| const VkDeviceSize bufferSize = pixelSize * params.dst.buffer.size; |
| const VkDeviceSize offsetSize = pixelSize * defaultFourthSize * defaultFourthSize; |
| deUint32 divisor = 1; |
| for (VkDeviceSize offset = 0; offset < bufferSize - offsetSize; offset += offsetSize, ++divisor) |
| { |
| const deUint32 bufferRowLength = defaultFourthSize; |
| const deUint32 bufferImageHeight = defaultFourthSize; |
| const VkExtent3D imageExtent = {defaultFourthSize / divisor, defaultFourthSize, 1}; |
| DE_ASSERT(!bufferRowLength || bufferRowLength >= imageExtent.width); |
| DE_ASSERT(!bufferImageHeight || bufferImageHeight >= imageExtent.height); |
| DE_ASSERT(imageExtent.width * imageExtent.height *imageExtent.depth <= offsetSize); |
| |
| CopyRegion region; |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| offset, // VkDeviceSize bufferOffset; |
| bufferRowLength, // deUint32 bufferRowLength; |
| bufferImageHeight, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {0, 0, 0}, // VkOffset3D imageOffset; |
| imageExtent // VkExtent3D imageExtent; |
| }; |
| region.bufferImageCopy = bufferImageCopy; |
| params.regions.push_back(region); |
| } |
| |
| group->addChild(new CopyImageToBufferTestCase(testCtx, "regions", "Copy from image to buffer with multiple regions", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.buffer.size = (defaultHalfSize - 1u) * defaultSize + defaultHalfSize; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| defaultSize, // deUint32 bufferRowLength; |
| defaultSize, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyImageToBufferTestCase(testCtx, "tightly_sized_buffer", "Copy from image to a buffer that is just large enough to contain the data", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.buffer.size = (defaultHalfSize - 1u) * defaultSize + defaultHalfSize + defaultFourthSize; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| defaultFourthSize, // VkDeviceSize bufferOffset; |
| defaultSize, // deUint32 bufferRowLength; |
| defaultSize, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyImageToBufferTestCase(testCtx, "tightly_sized_buffer_offset", "Copy from image to a buffer that is just large enough to contain the data", params)); |
| } |
| |
| { |
| TestParams params; |
| deUint32 arrayLayers = 16u; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultHalfExtent; |
| params.src.image.extent.depth = arrayLayers; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.dst.buffer.size = defaultHalfSize * defaultHalfSize * arrayLayers; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const int pixelSize = tcu::getPixelSize(mapVkFormat(params.src.image.format)); |
| for (deUint32 arrayLayerNdx = 0; arrayLayerNdx < arrayLayers; arrayLayerNdx++) |
| { |
| const VkDeviceSize offset = defaultHalfSize * defaultHalfSize * pixelSize * arrayLayerNdx; |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| offset, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayerNdx, // deUint32 baseArrayLayer; |
| 1u, // deUint32 layerCount; |
| }, // VkImageSubresourceLayers imageSubresource; |
| {0, 0, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| } |
| group->addChild(new CopyImageToBufferTestCase(testCtx, "array", "Copy each layer from array to buffer", params)); |
| } |
| |
| { |
| TestParams params; |
| deUint32 arrayLayers = 16u; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultHalfExtent; |
| params.src.image.extent.depth = arrayLayers; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.dst.buffer.size = defaultHalfSize * defaultHalfSize * arrayLayers; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const int pixelSize = tcu::getPixelSize(mapVkFormat(params.src.image.format)); |
| for (deUint32 arrayLayerNdx = 0; arrayLayerNdx < arrayLayers; arrayLayerNdx++) |
| { |
| const VkDeviceSize offset = defaultHalfSize * defaultHalfSize * pixelSize * arrayLayerNdx; |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| offset, // VkDeviceSize bufferOffset; |
| defaultHalfSize, // deUint32 bufferRowLength; |
| defaultHalfSize, // deUint32 bufferImageHeight; |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayerNdx, // deUint32 baseArrayLayer; |
| 1u, // deUint32 layerCount; |
| }, // VkImageSubresourceLayers imageSubresource; |
| {0, 0, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| } |
| group->addChild(new CopyImageToBufferTestCase(testCtx, "array_tightly_sized_buffer", "Copy each layer from array to tightly sized buffer", params)); |
| } |
| } |
| |
| void addBufferToDepthStencilTests(tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| const struct |
| { |
| const char* name; |
| const VkFormat format; |
| } depthAndStencilFormats[] = |
| { |
| { "d16_unorm", VK_FORMAT_D16_UNORM }, |
| { "x8_d24_unorm_pack32", VK_FORMAT_X8_D24_UNORM_PACK32 }, |
| { "d32_sfloat", VK_FORMAT_D32_SFLOAT }, |
| { "d16_unorm_s8_uint", VK_FORMAT_D16_UNORM_S8_UINT }, |
| { "d24_unorm_s8_uint", VK_FORMAT_D24_UNORM_S8_UINT }, |
| { "d32_sfloat_s8_uint", VK_FORMAT_D32_SFLOAT_S8_UINT } |
| }; |
| |
| const VkImageSubresourceLayers depthSourceLayer = |
| { |
| VK_IMAGE_ASPECT_DEPTH_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u, // deUint32 layerCount; |
| }; |
| |
| const VkBufferImageCopy bufferDepthCopy = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| depthSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {0, 0, 0}, // VkOffset3D imageOffset; |
| defaultExtent // VkExtent3D imageExtent; |
| }; |
| |
| const VkBufferImageCopy bufferDepthCopyOffset = |
| { |
| 32, // VkDeviceSize bufferOffset; |
| defaultHalfSize + defaultFourthSize, // deUint32 bufferRowLength; |
| defaultHalfSize + defaultFourthSize, // deUint32 bufferImageHeight; |
| depthSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| |
| const VkImageSubresourceLayers stencilSourceLayer = |
| { |
| VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u, // deUint32 layerCount; |
| }; |
| |
| const VkBufferImageCopy bufferStencilCopy = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| stencilSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {0, 0, 0}, // VkOffset3D imageOffset; |
| defaultExtent // VkExtent3D imageExtent; |
| }; |
| |
| const VkBufferImageCopy bufferStencilCopyOffset = |
| { |
| 32, // VkDeviceSize bufferOffset; |
| defaultHalfSize + defaultFourthSize, // deUint32 bufferRowLength; |
| defaultHalfSize + defaultFourthSize, // deUint32 bufferImageHeight; |
| stencilSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| |
| const bool useOffset[] = {false, true}; |
| |
| // Note: Depth stencil tests I want to do |
| // Formats: D16, D24S8, D32FS8 |
| // Test writing each component with separate CopyBufferToImage commands |
| // Test writing both components in one CopyBufferToImage command |
| // Swap order of writes of Depth & Stencil |
| // whole surface, subimages? |
| // Similar tests as BufferToImage? |
| for (const auto config : depthAndStencilFormats) |
| for (const auto offset : useOffset) |
| { |
| // TODO: Check that this format is supported before creating tests? |
| //if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D24_UNORM_S8_UINT)) |
| |
| CopyRegion copyDepthRegion; |
| CopyRegion copyStencilRegion; |
| TestParams params; |
| const tcu::TextureFormat format = mapVkFormat(config.format); |
| const bool hasDepth = tcu::hasDepthComponent(format.order); |
| const bool hasStencil = tcu::hasStencilComponent(format.order); |
| std::string description = config.name; |
| |
| if (offset) |
| { |
| copyDepthRegion.bufferImageCopy = bufferDepthCopyOffset; |
| copyStencilRegion.bufferImageCopy = bufferStencilCopyOffset; |
| description = "buffer_offset_" + description; |
| params.src.buffer.size = (defaultHalfSize - 1u) * defaultSize + defaultHalfSize + defaultFourthSize; |
| } |
| else |
| { |
| copyDepthRegion.bufferImageCopy = bufferDepthCopy; |
| copyStencilRegion.bufferImageCopy = bufferStencilCopy; |
| params.src.buffer.size = defaultSize * defaultSize; |
| } |
| |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = config.format; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| if (hasDepth && hasStencil) |
| { |
| params.singleCommand = DE_TRUE; |
| |
| params.regions.push_back(copyDepthRegion); |
| params.regions.push_back(copyStencilRegion); |
| |
| group->addChild(new CopyBufferToDepthStencilTestCase(testCtx, description + "_DS", "Copy from depth&stencil to image", params)); |
| |
| params.singleCommand = DE_FALSE; |
| |
| group->addChild(new CopyBufferToDepthStencilTestCase(testCtx, description + "_D_S", "Copy from depth then stencil to image", params)); |
| |
| params.regions.clear(); |
| params.regions.push_back(copyStencilRegion); |
| params.regions.push_back(copyDepthRegion); |
| |
| group->addChild(new CopyBufferToDepthStencilTestCase(testCtx, description + "_S_D", "Copy from depth then stencil to image", params)); |
| |
| params.singleCommand = DE_TRUE; |
| group->addChild(new CopyBufferToDepthStencilTestCase(testCtx, description + "_SD", "Copy from depth&stencil to image", params)); |
| } |
| |
| if (hasStencil) |
| { |
| params.regions.clear(); |
| params.regions.push_back(copyStencilRegion); |
| |
| group->addChild(new CopyBufferToDepthStencilTestCase(testCtx, description + "_S", "Copy from stencil to image", params)); |
| } |
| |
| if (hasDepth) |
| { |
| params.regions.clear(); |
| params.regions.push_back(copyDepthRegion); |
| |
| group->addChild(new CopyBufferToDepthStencilTestCase(testCtx, description + "_D", "Copy from depth to image", params)); |
| } |
| } |
| } |
| |
| void addBufferToImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| { |
| TestParams params; |
| params.src.buffer.size = defaultSize * defaultSize; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UINT; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {0, 0, 0}, // VkOffset3D imageOffset; |
| defaultExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyBufferToImageTestCase(testCtx, "whole", "Copy from buffer to image", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.buffer.size = defaultSize * defaultSize; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| CopyRegion region; |
| deUint32 divisor = 1; |
| for (int offset = 0; (offset + defaultFourthSize / divisor < defaultSize) && (defaultFourthSize > divisor); offset += defaultFourthSize / divisor++) |
| { |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {offset, defaultHalfSize, 0}, // VkOffset3D imageOffset; |
| {defaultFourthSize / divisor, defaultFourthSize / divisor, 1} // VkExtent3D imageExtent; |
| }; |
| region.bufferImageCopy = bufferImageCopy; |
| params.regions.push_back(region); |
| } |
| |
| group->addChild(new CopyBufferToImageTestCase(testCtx, "regions", "Copy from buffer to image with multiple regions", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.buffer.size = defaultSize * defaultSize; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| defaultFourthSize, // VkDeviceSize bufferOffset; |
| defaultHalfSize + defaultFourthSize, // deUint32 bufferRowLength; |
| defaultHalfSize + defaultFourthSize, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyBufferToImageTestCase(testCtx, "buffer_offset", "Copy from buffer to image with buffer offset", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.buffer.size = defaultSize * defaultSize; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8_UNORM; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| defaultFourthSize + 1u, // VkDeviceSize bufferOffset; |
| defaultHalfSize + defaultFourthSize, // deUint32 bufferRowLength; |
| defaultHalfSize + defaultFourthSize, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyBufferToImageTestCase(testCtx, "buffer_offset_relaxed", "Copy from buffer to image with buffer offset not a multiple of 4", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.buffer.size = (defaultHalfSize - 1u) * defaultSize + defaultHalfSize; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| defaultSize, // deUint32 bufferRowLength; |
| defaultSize, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyBufferToImageTestCase(testCtx, "tightly_sized_buffer", "Copy from buffer that is just large enough to contain the accessed elements", params)); |
| } |
| |
| { |
| TestParams params; |
| params.src.buffer.size = (defaultHalfSize - 1u) * defaultSize + defaultHalfSize + defaultFourthSize; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| defaultFourthSize, // VkDeviceSize bufferOffset; |
| defaultSize, // deUint32 bufferRowLength; |
| defaultSize, // deUint32 bufferImageHeight; |
| defaultSourceLayer, // VkImageSubresourceLayers imageSubresource; |
| {defaultFourthSize, defaultFourthSize, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new CopyBufferToImageTestCase(testCtx, "tightly_sized_buffer_offset", "Copy from buffer that is just large enough to contain the accessed elements", params)); |
| } |
| |
| { |
| TestParams params; |
| deUint32 arrayLayers = 16u; |
| params.src.buffer.size = defaultHalfSize * defaultHalfSize * arrayLayers; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultHalfExtent; |
| params.dst.image.extent.depth = arrayLayers; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const int pixelSize = tcu::getPixelSize(mapVkFormat(params.dst.image.format)); |
| for (deUint32 arrayLayerNdx = 0; arrayLayerNdx < arrayLayers; arrayLayerNdx++) |
| { |
| const VkDeviceSize offset = defaultHalfSize * defaultHalfSize * pixelSize * arrayLayerNdx; |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| offset, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayerNdx, // deUint32 baseArrayLayer; |
| 1u, // deUint32 layerCount; |
| }, // VkImageSubresourceLayers imageSubresource; |
| {0, 0, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| } |
| group->addChild(new CopyBufferToImageTestCase(testCtx, "array", "Copy from a different part of the buffer to each layer", params)); |
| } |
| |
| { |
| TestParams params; |
| deUint32 arrayLayers = 16u; |
| params.src.buffer.size = defaultHalfSize * defaultHalfSize * arrayLayers; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultHalfExtent; |
| params.dst.image.extent.depth = arrayLayers; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const int pixelSize = tcu::getPixelSize(mapVkFormat(params.dst.image.format)); |
| for (deUint32 arrayLayerNdx = 0; arrayLayerNdx < arrayLayers; arrayLayerNdx++) |
| { |
| const VkDeviceSize offset = defaultHalfSize * defaultHalfSize * pixelSize * arrayLayerNdx; |
| const VkBufferImageCopy bufferImageCopy = |
| { |
| offset, // VkDeviceSize bufferOffset; |
| defaultHalfSize, // deUint32 bufferRowLength; |
| defaultHalfSize, // deUint32 bufferImageHeight; |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| arrayLayerNdx, // deUint32 baseArrayLayer; |
| 1u, // deUint32 layerCount; |
| }, // VkImageSubresourceLayers imageSubresource; |
| {0, 0, 0}, // VkOffset3D imageOffset; |
| defaultHalfExtent // VkExtent3D imageExtent; |
| }; |
| CopyRegion copyRegion; |
| copyRegion.bufferImageCopy = bufferImageCopy; |
| |
| params.regions.push_back(copyRegion); |
| } |
| group->addChild(new CopyBufferToImageTestCase(testCtx, "array_tightly_sized_buffer", "Copy from different part of tightly sized buffer to each layer", params)); |
| } |
| } |
| |
| void addBufferToBufferTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| { |
| TestParams params; |
| params.src.buffer.size = defaultSize; |
| params.dst.buffer.size = defaultSize; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferCopy bufferCopy = |
| { |
| 0u, // VkDeviceSize srcOffset; |
| 0u, // VkDeviceSize dstOffset; |
| defaultSize, // VkDeviceSize size; |
| }; |
| |
| CopyRegion copyRegion; |
| copyRegion.bufferCopy = bufferCopy; |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new BufferToBufferTestCase(testCtx, "whole", "Whole buffer", params)); |
| } |
| |
| // Filter is VK_FILTER_NEAREST. |
| { |
| TestParams params; |
| params.src.buffer.size = defaultFourthSize; |
| params.dst.buffer.size = defaultFourthSize; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkBufferCopy bufferCopy = |
| { |
| 12u, // VkDeviceSize srcOffset; |
| 4u, // VkDeviceSize dstOffset; |
| 1u, // VkDeviceSize size; |
| }; |
| |
| CopyRegion copyRegion; |
| copyRegion.bufferCopy = bufferCopy; |
| params.regions.push_back(copyRegion); |
| |
| group->addChild(new BufferToBufferTestCase(testCtx, "partial", "Partial", params)); |
| } |
| |
| { |
| const deUint32 size = 16; |
| TestParams params; |
| params.src.buffer.size = size; |
| params.dst.buffer.size = size * (size + 1); |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| // Copy region with size 1..size |
| for (unsigned int i = 1; i <= size; i++) |
| { |
| const VkBufferCopy bufferCopy = |
| { |
| 0, // VkDeviceSize srcOffset; |
| i * size, // VkDeviceSize dstOffset; |
| i, // VkDeviceSize size; |
| }; |
| |
| CopyRegion copyRegion; |
| copyRegion.bufferCopy = bufferCopy; |
| params.regions.push_back(copyRegion); |
| } |
| |
| group->addChild(new BufferToBufferTestCase(testCtx, "regions", "Multiple regions", params)); |
| } |
| } |
| |
| void addBlittingImageSimpleTests (tcu::TestCaseGroup* group, TestParams& params) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| // Filter is VK_FILTER_NEAREST. |
| { |
| params.filter = VK_FILTER_NEAREST; |
| const std::string description = "Nearest filter"; |
| |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params)); |
| |
| params.dst.image.format = VK_FORMAT_R32_SFLOAT; |
| const std::string descriptionOfRGBAToR32 (description + " and different formats (R8G8B8A8 -> R32)"); |
| group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params)); |
| |
| params.dst.image.format = VK_FORMAT_B8G8R8A8_UNORM; |
| const std::string descriptionOfRGBAToBGRA (description + " and different formats (R8G8B8A8 -> B8G8R8A8)"); |
| group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params)); |
| } |
| |
| // Filter is VK_FILTER_LINEAR. |
| { |
| params.filter = VK_FILTER_LINEAR; |
| const std::string description = "Linear filter"; |
| |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| group->addChild(new BlitImageTestCase(testCtx, "linear", description, params)); |
| |
| params.dst.image.format = VK_FORMAT_R32_SFLOAT; |
| const std::string descriptionOfRGBAToR32 (description + " and different formats (R8G8B8A8 -> R32)"); |
| group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params)); |
| |
| params.dst.image.format = VK_FORMAT_B8G8R8A8_UNORM; |
| const std::string descriptionOfRGBAToBGRA (description + " and different formats (R8G8B8A8 -> B8G8R8A8)"); |
| group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params)); |
| } |
| |
| // Filter is VK_FILTER_CUBIC_EXT. |
| // Cubic filtering can only be used with 2D images. |
| if (params.dst.image.imageType == VK_IMAGE_TYPE_2D) |
| { |
| params.filter = VK_FILTER_CUBIC_EXT; |
| const std::string description = "Cubic filter"; |
| |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| group->addChild(new BlitImageTestCase(testCtx, "cubic", description, params)); |
| |
| params.dst.image.format = VK_FORMAT_R32_SFLOAT; |
| const std::string descriptionOfRGBAToR32(description + " and different formats (R8G8B8A8 -> R32)"); |
| group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_cubic", descriptionOfRGBAToR32, params)); |
| |
| params.dst.image.format = VK_FORMAT_B8G8R8A8_UNORM; |
| const std::string descriptionOfRGBAToBGRA(description + " and different formats (R8G8B8A8 -> B8G8R8A8)"); |
| group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_cubic", descriptionOfRGBAToBGRA, params)); |
| } |
| } |
| |
| void addBlittingImageSimpleWholeTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| const deInt32 imageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultSize : 1; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.extent.depth = imageDepth; |
| params.dst.image.extent.depth = imageDepth; |
| |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| { 0, 0, 0 }, |
| { defaultSize, defaultSize, imageDepth } |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| { 0, 0, 0 }, |
| { defaultSize, defaultSize, imageDepth } |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleMirrorXYTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| const deInt32 imageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultSize : 1; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.extent.depth = imageDepth; |
| params.dst.image.extent.depth = imageDepth; |
| |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize, defaultSize, imageDepth} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {defaultSize, defaultSize, 0}, |
| {0, 0, imageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleMirrorXTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| const deInt32 imageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultSize : 1; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.extent.depth = imageDepth; |
| params.dst.image.extent.depth = imageDepth; |
| |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize, defaultSize, imageDepth} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {defaultSize, 0, 0}, |
| {0, defaultSize, imageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleMirrorYTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| const deInt32 imageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultSize : 1; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.extent.depth = imageDepth; |
| params.dst.image.extent.depth = imageDepth; |
| |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize, defaultSize, imageDepth} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {0, defaultSize, 0}, |
| {defaultSize, 0, imageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleMirrorZTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| DE_ASSERT(params.src.image.imageType == VK_IMAGE_TYPE_3D); |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.extent.depth = defaultSize; |
| params.dst.image.extent.depth = defaultSize; |
| |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize, defaultSize, defaultSize} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {0, 0, defaultSize}, |
| {defaultSize, defaultSize, 0} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleMirrorSubregionsTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| const deInt32 imageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultSize : 1; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.extent.depth = imageDepth; |
| params.dst.image.extent.depth = imageDepth; |
| |
| // No mirroring. |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultHalfSize, defaultHalfSize, imageDepth} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {0, 0, 0}, |
| {defaultHalfSize, defaultHalfSize, imageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| // Flipping y coordinates. |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {defaultHalfSize, 0, 0}, |
| {defaultSize, defaultHalfSize, imageDepth} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {defaultHalfSize, defaultHalfSize, 0}, |
| {defaultSize, 0, imageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| // Flipping x coordinates. |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, defaultHalfSize, 0}, |
| {defaultHalfSize, defaultSize, imageDepth} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {defaultHalfSize, defaultHalfSize, 0}, |
| {0, defaultSize, imageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| // Flipping x and y coordinates. |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {defaultHalfSize, defaultHalfSize, 0}, |
| {defaultSize, defaultSize, imageDepth} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {defaultSize, defaultSize, 0}, |
| {defaultHalfSize, defaultHalfSize, imageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleScalingWhole1Tests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| const deInt32 imageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultSize : 1; |
| const deInt32 halfImageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultHalfSize : 1; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultHalfExtent; |
| params.src.image.extent.depth = imageDepth; |
| params.dst.image.extent.depth = halfImageDepth; |
| |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize, defaultSize, imageDepth} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {0, 0, 0}, |
| {defaultHalfSize, defaultHalfSize, halfImageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleScalingWhole2Tests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| const deInt32 imageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultSize : 1; |
| const deInt32 halfImageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultHalfSize : 1; |
| params.src.image.extent = defaultHalfExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.extent.depth = halfImageDepth; |
| params.dst.image.extent.depth = imageDepth; |
| |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultHalfSize, defaultHalfSize, halfImageDepth} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize, defaultSize, imageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleScalingAndOffsetTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| const deInt32 imageDepth = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultSize : 1; |
| const deInt32 srcDepthOffset = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultFourthSize : 0; |
| const deInt32 srcDepthSize = params.src.image.imageType == VK_IMAGE_TYPE_3D ? defaultFourthSize * 3 : 1; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.extent.depth = imageDepth; |
| params.dst.image.extent.depth = imageDepth; |
| |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {defaultFourthSize, defaultFourthSize, srcDepthOffset}, |
| {defaultFourthSize*3, defaultFourthSize*3, srcDepthSize} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize, defaultSize, imageDepth} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| CopyRegion region; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleWithoutScalingPartialTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| DE_ASSERT(params.src.image.imageType == params.dst.image.imageType); |
| const bool is3dBlit = params.src.image.imageType == VK_IMAGE_TYPE_3D; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| |
| if (is3dBlit) |
| { |
| params.src.image.extent.depth = defaultSize; |
| params.dst.image.extent.depth = defaultSize; |
| } |
| |
| { |
| CopyRegion region; |
| for (int i = 0; i < defaultSize; i += defaultFourthSize) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {defaultSize - defaultFourthSize - i, defaultSize - defaultFourthSize - i, is3dBlit ? defaultSize - defaultFourthSize - i : 0}, |
| {defaultSize - i, defaultSize - i, is3dBlit ? defaultSize - i : 1} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {i, i, is3dBlit ? i : 0}, |
| {i + defaultFourthSize, i + defaultFourthSize, is3dBlit ? i + defaultFourthSize : 1} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| } |
| |
| addBlittingImageSimpleTests(group, params); |
| } |
| |
| void addBlittingImageSimpleTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| TestParams params; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| addTestGroup(group, "whole", "Blit without scaling (whole)", addBlittingImageSimpleWholeTests, params); |
| addTestGroup(group, "mirror_xy", "Flipping x and y coordinates (whole)", addBlittingImageSimpleMirrorXYTests, params); |
| addTestGroup(group, "mirror_x", "Flipping x coordinates (whole)", addBlittingImageSimpleMirrorXTests, params); |
| addTestGroup(group, "mirror_y", "Flipping y coordinates (whole)", addBlittingImageSimpleMirrorYTests, params); |
| addTestGroup(group, "mirror_subregions", "Mirroring subregions in image (no flip, y flip, x flip, xy flip)", addBlittingImageSimpleMirrorSubregionsTests, params); |
| addTestGroup(group, "scaling_whole1", "Blit with scaling (whole, src extent bigger)", addBlittingImageSimpleScalingWhole1Tests, params); |
| addTestGroup(group, "scaling_whole2", "Blit with scaling (whole, dst extent bigger)", addBlittingImageSimpleScalingWhole2Tests, params); |
| addTestGroup(group, "scaling_and_offset", "Blit with scaling and offset (whole, dst extent bigger)", addBlittingImageSimpleScalingAndOffsetTests, params); |
| addTestGroup(group, "without_scaling_partial", "Blit without scaling (partial)", addBlittingImageSimpleWithoutScalingPartialTests, params); |
| |
| params.src.image.imageType = VK_IMAGE_TYPE_3D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_3D; |
| addTestGroup(group, "whole_3d", "3D blit without scaling (whole)", addBlittingImageSimpleWholeTests, params); |
| addTestGroup(group, "mirror_xy_3d", "Flipping x and y coordinates of a 3D image (whole)", addBlittingImageSimpleMirrorXYTests, params); |
| addTestGroup(group, "mirror_x_3d", "Flipping x coordinates of a 3D image (whole)", addBlittingImageSimpleMirrorXTests, params); |
| addTestGroup(group, "mirror_y_3d", "Flipping y coordinates of a 3D image (whole)", addBlittingImageSimpleMirrorYTests, params); |
| addTestGroup(group, "mirror_z_3d", "Flipping z coordinates of a 3D image (whole)", addBlittingImageSimpleMirrorZTests, params); |
| addTestGroup(group, "mirror_subregions_3d", "Mirroring subregions in a 3D image (no flip, y flip, x flip, xy flip)", addBlittingImageSimpleMirrorSubregionsTests, params); |
| addTestGroup(group, "scaling_whole1_3d", "3D blit a with scaling (whole, src extent bigger)", addBlittingImageSimpleScalingWhole1Tests, params); |
| addTestGroup(group, "scaling_whole2_3d", "3D blit with scaling (whole, dst extent bigger)", addBlittingImageSimpleScalingWhole2Tests, params); |
| addTestGroup(group, "scaling_and_offset_3d", "3D blit with scaling and offset (whole, dst extent bigger)", addBlittingImageSimpleScalingAndOffsetTests, params); |
| addTestGroup(group, "without_scaling_partial_3d", "3D blit without scaling (partial)", addBlittingImageSimpleWithoutScalingPartialTests, params); |
| } |
| |
| enum FilterMaskBits |
| { |
| FILTER_MASK_NEAREST = 0, // Always tested. |
| FILTER_MASK_LINEAR = (1u << 0), |
| FILTER_MASK_CUBIC = (1u << 1), |
| }; |
| |
| using FilterMask = deUint32; |
| |
| FilterMask makeFilterMask (bool onlyNearest, bool discardCubicFilter) |
| { |
| FilterMask mask = FILTER_MASK_NEAREST; |
| |
| if (!onlyNearest) |
| { |
| mask |= FILTER_MASK_LINEAR; |
| if (!discardCubicFilter) |
| mask |= FILTER_MASK_CUBIC; |
| } |
| |
| return mask; |
| } |
| |
| struct BlitColorTestParams |
| { |
| TestParams params; |
| const VkFormat* compatibleFormats; |
| FilterMask testFilters; |
| }; |
| |
| bool isAllowedBlittingAllFormatsColorSrcFormatTests(const BlitColorTestParams& testParams) |
| { |
| bool result = true; |
| |
| if (testParams.params.allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| DE_ASSERT(!dedicatedAllocationBlittingFormatsToTestSet.empty()); |
| |
| result = |
| de::contains(dedicatedAllocationBlittingFormatsToTestSet, testParams.params.dst.image.format) || |
| de::contains(dedicatedAllocationBlittingFormatsToTestSet, testParams.params.src.image.format); |
| } |
| |
| return result; |
| } |
| |
| const VkFormat linearOtherImageFormatsToTest[] = |
| { |
| // From compatibleFormats8Bit |
| VK_FORMAT_R4G4_UNORM_PACK8, |
| VK_FORMAT_R8_SRGB, |
| |
| // From compatibleFormats16Bit |
| VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| VK_FORMAT_R16_SFLOAT, |
| |
| // From compatibleFormats24Bit |
| VK_FORMAT_R8G8B8_UNORM, |
| VK_FORMAT_B8G8R8_SRGB, |
| |
| // From compatibleFormats32Bit |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R32_SFLOAT, |
| |
| // From compatibleFormats48Bit |
| VK_FORMAT_R16G16B16_UNORM, |
| VK_FORMAT_R16G16B16_SFLOAT, |
| |
| // From compatibleFormats64Bit |
| VK_FORMAT_R16G16B16A16_UNORM, |
| VK_FORMAT_R64_SFLOAT, |
| |
| // From compatibleFormats96Bit |
| VK_FORMAT_R32G32B32_UINT, |
| VK_FORMAT_R32G32B32_SFLOAT, |
| |
| // From compatibleFormats128Bit |
| VK_FORMAT_R32G32B32A32_UINT, |
| VK_FORMAT_R64G64_SFLOAT, |
| |
| // From compatibleFormats192Bit |
| VK_FORMAT_R64G64B64_UINT, |
| VK_FORMAT_R64G64B64_SFLOAT, |
| |
| // From compatibleFormats256Bit |
| VK_FORMAT_R64G64B64A64_UINT, |
| VK_FORMAT_R64G64B64A64_SFLOAT, |
| }; |
| |
| std::string getBlitImageTilingLayoutCaseName (VkImageTiling tiling, VkImageLayout layout) |
| { |
| switch (tiling) |
| { |
| case VK_IMAGE_TILING_OPTIMAL: |
| return getImageLayoutCaseName(layout); |
| case VK_IMAGE_TILING_LINEAR: |
| return "linear"; |
| default: |
| DE_ASSERT(false); |
| return ""; |
| } |
| } |
| |
| void addBlittingImageAllFormatsColorSrcFormatDstFormatTests (tcu::TestCaseGroup* group, BlitColorTestParams testParams) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| FormatSet linearOtherImageFormatsToTestSet; |
| const int numOfOtherImageFormatsToTestFilter = DE_LENGTH_OF_ARRAY(linearOtherImageFormatsToTest); |
| for (int otherImageFormatsIndex = 0; otherImageFormatsIndex < numOfOtherImageFormatsToTestFilter; ++otherImageFormatsIndex) |
| linearOtherImageFormatsToTestSet.insert(linearOtherImageFormatsToTest[otherImageFormatsIndex]); |
| |
| const VkImageTiling blitSrcTilings[] = |
| { |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_TILING_LINEAR, |
| }; |
| const VkImageLayout blitSrcLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| const VkImageTiling blitDstTilings[] = |
| { |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_TILING_LINEAR, |
| }; |
| const VkImageLayout blitDstLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| |
| for (int srcTilingNdx = 0u; srcTilingNdx < DE_LENGTH_OF_ARRAY(blitSrcTilings); ++srcTilingNdx) |
| { |
| testParams.params.src.image.tiling = blitSrcTilings[srcTilingNdx]; |
| |
| for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(blitSrcLayouts); ++srcLayoutNdx) |
| { |
| testParams.params.src.image.operationLayout = blitSrcLayouts[srcLayoutNdx]; |
| |
| // Don't bother testing VK_IMAGE_TILING_LINEAR + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL as it's likely to be the same as VK_IMAGE_LAYOUT_GENERAL |
| if (testParams.params.src.image.tiling == VK_IMAGE_TILING_LINEAR && testParams.params.src.image.operationLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) |
| continue; |
| |
| for (int dstTilingNdx = 0u; dstTilingNdx < DE_LENGTH_OF_ARRAY(blitDstTilings); ++dstTilingNdx) |
| { |
| testParams.params.dst.image.tiling = blitDstTilings[dstTilingNdx]; |
| |
| for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(blitDstLayouts); ++dstLayoutNdx) |
| { |
| testParams.params.dst.image.operationLayout = blitDstLayouts[dstLayoutNdx]; |
| |
| // Don't bother testing VK_IMAGE_TILING_LINEAR + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL as it's likely to be the same as VK_IMAGE_LAYOUT_GENERAL |
| if (testParams.params.dst.image.tiling == VK_IMAGE_TILING_LINEAR && testParams.params.dst.image.operationLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) |
| continue; |
| |
| if ((testParams.params.dst.image.tiling == VK_IMAGE_TILING_LINEAR && !de::contains(linearOtherImageFormatsToTestSet, testParams.params.src.image.format)) || |
| (testParams.params.src.image.tiling == VK_IMAGE_TILING_LINEAR && !de::contains(linearOtherImageFormatsToTestSet, testParams.params.dst.image.format))) |
| continue; |
| |
| testParams.params.filter = VK_FILTER_NEAREST; |
| const std::string testName = getBlitImageTilingLayoutCaseName(testParams.params.src.image.tiling, testParams.params.src.image.operationLayout) + "_" + |
| getBlitImageTilingLayoutCaseName(testParams.params.dst.image.tiling, testParams.params.dst.image.operationLayout); |
| const std::string description = "Blit from layout " + getBlitImageTilingLayoutCaseName(testParams.params.src.image.tiling, testParams.params.src.image.operationLayout) + |
| " to " + getBlitImageTilingLayoutCaseName(testParams.params.dst.image.tiling, testParams.params.dst.image.operationLayout); |
| group->addChild(new BlitImageTestCase(testCtx, testName + "_nearest", description, testParams.params)); |
| |
| if (testParams.testFilters & FILTER_MASK_LINEAR) |
| { |
| testParams.params.filter = VK_FILTER_LINEAR; |
| group->addChild(new BlitImageTestCase(testCtx, testName + "_linear", description, testParams.params)); |
| } |
| |
| if (testParams.testFilters & FILTER_MASK_CUBIC) |
| { |
| testParams.params.filter = VK_FILTER_CUBIC_EXT; |
| group->addChild(new BlitImageTestCase(testCtx, testName + "_cubic", description, testParams.params)); |
| } |
| |
| if ((testParams.params.src.image.imageType == VK_IMAGE_TYPE_3D) && !isCompressedFormat(testParams.params.src.image.format)) |
| { |
| const struct |
| { |
| FillMode mode; |
| const char* name; |
| } modeList[] = |
| { |
| { FILL_MODE_BLUE_RED_X, "x" }, |
| { FILL_MODE_BLUE_RED_Y, "y" }, |
| { FILL_MODE_BLUE_RED_Z, "z" }, |
| }; |
| |
| auto otherParams = testParams; |
| otherParams.params.dst.image.fillMode = FILL_MODE_WHITE; |
| |
| for (int i = 0; i < DE_LENGTH_OF_ARRAY(modeList); ++i) |
| { |
| otherParams.params.src.image.fillMode = modeList[i].mode; |
| |
| otherParams.params.filter = VK_FILTER_LINEAR; |
| group->addChild(new BlitImageTestCase(testCtx, testName + "_linear_stripes_" + modeList[i].name, description, otherParams.params)); |
| |
| otherParams.params.filter = VK_FILTER_NEAREST; |
| group->addChild(new BlitImageTestCase(testCtx, testName + "_nearest_stripes_" + modeList[i].name, description, otherParams.params)); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| void addBlittingImageAllFormatsColorSrcFormatTests (tcu::TestCaseGroup* group, BlitColorTestParams testParams) |
| { |
| VkFormat srcFormat = testParams.params.src.image.format; |
| |
| if (testParams.compatibleFormats) |
| { |
| for (int dstFormatIndex = 0; testParams.compatibleFormats[dstFormatIndex] != VK_FORMAT_UNDEFINED; ++dstFormatIndex) |
| { |
| testParams.params.dst.image.format = testParams.compatibleFormats[dstFormatIndex]; |
| if (!isSupportedByFramework(testParams.params.dst.image.format)) |
| continue; |
| |
| if (!isAllowedBlittingAllFormatsColorSrcFormatTests(testParams)) |
| continue; |
| |
| const std::string description = "Blit destination format " + getFormatCaseName(testParams.params.dst.image.format); |
| addTestGroup(group, getFormatCaseName(testParams.params.dst.image.format), description, addBlittingImageAllFormatsColorSrcFormatDstFormatTests, testParams); |
| } |
| } |
| |
| // If testParams.compatibleFormats is nullptr, the destination format will be copied from the source format |
| // When testParams.compatibleFormats is not nullptr but format is compressed we also need to add that format |
| // as it is not on compatibleFormats list |
| if (!testParams.compatibleFormats || isCompressedFormat(srcFormat)) |
| { |
| testParams.params.dst.image.format = srcFormat; |
| |
| const std::string description = "Blit destination format " + getFormatCaseName(srcFormat); |
| addTestGroup(group, getFormatCaseName(srcFormat), description, addBlittingImageAllFormatsColorSrcFormatDstFormatTests, testParams); |
| } |
| } |
| |
| const VkFormat compatibleFormatsUInts[] = |
| { |
| VK_FORMAT_R8_UINT, |
| VK_FORMAT_R8G8_UINT, |
| VK_FORMAT_R8G8B8_UINT, |
| VK_FORMAT_B8G8R8_UINT, |
| VK_FORMAT_R8G8B8A8_UINT, |
| VK_FORMAT_B8G8R8A8_UINT, |
| VK_FORMAT_A8B8G8R8_UINT_PACK32, |
| VK_FORMAT_A2R10G10B10_UINT_PACK32, |
| VK_FORMAT_A2B10G10R10_UINT_PACK32, |
| VK_FORMAT_R16_UINT, |
| VK_FORMAT_R16G16_UINT, |
| VK_FORMAT_R16G16B16_UINT, |
| VK_FORMAT_R16G16B16A16_UINT, |
| VK_FORMAT_R32_UINT, |
| VK_FORMAT_R32G32_UINT, |
| VK_FORMAT_R32G32B32_UINT, |
| VK_FORMAT_R32G32B32A32_UINT, |
| VK_FORMAT_R64_UINT, |
| VK_FORMAT_R64G64_UINT, |
| VK_FORMAT_R64G64B64_UINT, |
| VK_FORMAT_R64G64B64A64_UINT, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormatsSInts[] = |
| { |
| VK_FORMAT_R8_SINT, |
| VK_FORMAT_R8G8_SINT, |
| VK_FORMAT_R8G8B8_SINT, |
| VK_FORMAT_B8G8R8_SINT, |
| VK_FORMAT_R8G8B8A8_SINT, |
| VK_FORMAT_B8G8R8A8_SINT, |
| VK_FORMAT_A8B8G8R8_SINT_PACK32, |
| VK_FORMAT_A2R10G10B10_SINT_PACK32, |
| VK_FORMAT_A2B10G10R10_SINT_PACK32, |
| VK_FORMAT_R16_SINT, |
| VK_FORMAT_R16G16_SINT, |
| VK_FORMAT_R16G16B16_SINT, |
| VK_FORMAT_R16G16B16A16_SINT, |
| VK_FORMAT_R32_SINT, |
| VK_FORMAT_R32G32_SINT, |
| VK_FORMAT_R32G32B32_SINT, |
| VK_FORMAT_R32G32B32A32_SINT, |
| VK_FORMAT_R64_SINT, |
| VK_FORMAT_R64G64_SINT, |
| VK_FORMAT_R64G64B64_SINT, |
| VK_FORMAT_R64G64B64A64_SINT, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| const VkFormat compatibleFormatsFloats[] = |
| { |
| VK_FORMAT_R4G4_UNORM_PACK8, |
| VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| VK_FORMAT_B4G4R4A4_UNORM_PACK16, |
| VK_FORMAT_R5G6B5_UNORM_PACK16, |
| VK_FORMAT_B5G6R5_UNORM_PACK16, |
| VK_FORMAT_R5G5B5A1_UNORM_PACK16, |
| VK_FORMAT_B5G5R5A1_UNORM_PACK16, |
| VK_FORMAT_A1R5G5B5_UNORM_PACK16, |
| VK_FORMAT_R8_UNORM, |
| VK_FORMAT_R8_SNORM, |
| VK_FORMAT_R8_USCALED, |
| VK_FORMAT_R8_SSCALED, |
| VK_FORMAT_R8G8_UNORM, |
| VK_FORMAT_R8G8_SNORM, |
| VK_FORMAT_R8G8_USCALED, |
| VK_FORMAT_R8G8_SSCALED, |
| VK_FORMAT_R8G8B8_UNORM, |
| VK_FORMAT_R8G8B8_SNORM, |
| VK_FORMAT_R8G8B8_USCALED, |
| VK_FORMAT_R8G8B8_SSCALED, |
| VK_FORMAT_B8G8R8_UNORM, |
| VK_FORMAT_B8G8R8_SNORM, |
| VK_FORMAT_B8G8R8_USCALED, |
| VK_FORMAT_B8G8R8_SSCALED, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R8G8B8A8_SNORM, |
| VK_FORMAT_R8G8B8A8_USCALED, |
| VK_FORMAT_R8G8B8A8_SSCALED, |
| VK_FORMAT_B8G8R8A8_UNORM, |
| VK_FORMAT_B8G8R8A8_SNORM, |
| VK_FORMAT_B8G8R8A8_USCALED, |
| VK_FORMAT_B8G8R8A8_SSCALED, |
| VK_FORMAT_A8B8G8R8_UNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_SNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_USCALED_PACK32, |
| VK_FORMAT_A8B8G8R8_SSCALED_PACK32, |
| VK_FORMAT_A2R10G10B10_UNORM_PACK32, |
| VK_FORMAT_A2R10G10B10_SNORM_PACK32, |
| VK_FORMAT_A2R10G10B10_USCALED_PACK32, |
| VK_FORMAT_A2R10G10B10_SSCALED_PACK32, |
| VK_FORMAT_A2B10G10R10_UNORM_PACK32, |
| VK_FORMAT_A2B10G10R10_SNORM_PACK32, |
| VK_FORMAT_A2B10G10R10_USCALED_PACK32, |
| VK_FORMAT_A2B10G10R10_SSCALED_PACK32, |
| VK_FORMAT_R16_UNORM, |
| VK_FORMAT_R16_SNORM, |
| VK_FORMAT_R16_USCALED, |
| VK_FORMAT_R16_SSCALED, |
| VK_FORMAT_R16_SFLOAT, |
| VK_FORMAT_R16G16_UNORM, |
| VK_FORMAT_R16G16_SNORM, |
| VK_FORMAT_R16G16_USCALED, |
| VK_FORMAT_R16G16_SSCALED, |
| VK_FORMAT_R16G16_SFLOAT, |
| VK_FORMAT_R16G16B16_UNORM, |
| VK_FORMAT_R16G16B16_SNORM, |
| VK_FORMAT_R16G16B16_USCALED, |
| VK_FORMAT_R16G16B16_SSCALED, |
| VK_FORMAT_R16G16B16_SFLOAT, |
| VK_FORMAT_R16G16B16A16_UNORM, |
| VK_FORMAT_R16G16B16A16_SNORM, |
| VK_FORMAT_R16G16B16A16_USCALED, |
| VK_FORMAT_R16G16B16A16_SSCALED, |
| VK_FORMAT_R16G16B16A16_SFLOAT, |
| VK_FORMAT_R32_SFLOAT, |
| VK_FORMAT_R32G32_SFLOAT, |
| VK_FORMAT_R32G32B32_SFLOAT, |
| VK_FORMAT_R32G32B32A32_SFLOAT, |
| VK_FORMAT_R64_SFLOAT, |
| VK_FORMAT_R64G64_SFLOAT, |
| VK_FORMAT_R64G64B64_SFLOAT, |
| VK_FORMAT_R64G64B64A64_SFLOAT, |
| VK_FORMAT_B10G11R11_UFLOAT_PACK32, |
| VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, |
| |
| VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, |
| VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, |
| |
| VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| |
| const VkFormat compressedFormatsFloats[] = |
| { |
| VK_FORMAT_BC1_RGB_UNORM_BLOCK, |
| VK_FORMAT_BC1_RGBA_UNORM_BLOCK, |
| VK_FORMAT_BC2_UNORM_BLOCK, |
| VK_FORMAT_BC3_UNORM_BLOCK, |
| VK_FORMAT_BC4_UNORM_BLOCK, |
| VK_FORMAT_BC4_SNORM_BLOCK, |
| VK_FORMAT_BC5_UNORM_BLOCK, |
| VK_FORMAT_BC5_SNORM_BLOCK, |
| VK_FORMAT_BC6H_UFLOAT_BLOCK, |
| VK_FORMAT_BC6H_SFLOAT_BLOCK, |
| VK_FORMAT_BC7_UNORM_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, |
| VK_FORMAT_EAC_R11_UNORM_BLOCK, |
| VK_FORMAT_EAC_R11_SNORM_BLOCK, |
| VK_FORMAT_EAC_R11G11_UNORM_BLOCK, |
| VK_FORMAT_EAC_R11G11_SNORM_BLOCK, |
| VK_FORMAT_ASTC_4x4_UNORM_BLOCK, |
| VK_FORMAT_ASTC_5x4_UNORM_BLOCK, |
| VK_FORMAT_ASTC_5x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_6x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_6x6_UNORM_BLOCK, |
| VK_FORMAT_ASTC_8x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_8x6_UNORM_BLOCK, |
| VK_FORMAT_ASTC_8x8_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x6_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x8_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x10_UNORM_BLOCK, |
| VK_FORMAT_ASTC_12x10_UNORM_BLOCK, |
| VK_FORMAT_ASTC_12x12_UNORM_BLOCK, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| |
| const VkFormat compatibleFormatsSrgb[] = |
| { |
| VK_FORMAT_R8_SRGB, |
| VK_FORMAT_R8G8_SRGB, |
| VK_FORMAT_R8G8B8_SRGB, |
| VK_FORMAT_B8G8R8_SRGB, |
| VK_FORMAT_R8G8B8A8_SRGB, |
| VK_FORMAT_B8G8R8A8_SRGB, |
| VK_FORMAT_A8B8G8R8_SRGB_PACK32, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| |
| const VkFormat compressedFormatsSrgb[] = |
| { |
| VK_FORMAT_BC1_RGB_SRGB_BLOCK, |
| VK_FORMAT_BC1_RGBA_SRGB_BLOCK, |
| VK_FORMAT_BC2_SRGB_BLOCK, |
| VK_FORMAT_BC3_SRGB_BLOCK, |
| VK_FORMAT_BC7_SRGB_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, |
| VK_FORMAT_ASTC_4x4_SRGB_BLOCK, |
| VK_FORMAT_ASTC_5x4_SRGB_BLOCK, |
| VK_FORMAT_ASTC_5x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_6x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_6x6_SRGB_BLOCK, |
| VK_FORMAT_ASTC_8x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_8x6_SRGB_BLOCK, |
| VK_FORMAT_ASTC_8x8_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x6_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x8_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x10_SRGB_BLOCK, |
| VK_FORMAT_ASTC_12x10_SRGB_BLOCK, |
| VK_FORMAT_ASTC_12x12_SRGB_BLOCK, |
| |
| VK_FORMAT_UNDEFINED |
| }; |
| |
| const VkFormat dedicatedAllocationBlittingFormatsToTest[] = |
| { |
| // compatibleFormatsUInts |
| VK_FORMAT_R8_UINT, |
| VK_FORMAT_R64G64B64A64_UINT, |
| |
| // compatibleFormatsSInts |
| VK_FORMAT_R8_SINT, |
| VK_FORMAT_R64G64B64A64_SINT, |
| |
| // compatibleFormatsFloats |
| VK_FORMAT_R4G4_UNORM_PACK8, |
| VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, |
| |
| // compatibleFormatsSrgb |
| VK_FORMAT_R8_SRGB, |
| VK_FORMAT_A8B8G8R8_SRGB_PACK32, |
| }; |
| |
| // skip cubic filtering test for the following data formats |
| const FormatSet onlyNearestAndLinearFormatsToTest = |
| { |
| VK_FORMAT_A8B8G8R8_USCALED_PACK32, |
| VK_FORMAT_A8B8G8R8_SSCALED_PACK32, |
| VK_FORMAT_A8B8G8R8_UINT_PACK32, |
| VK_FORMAT_A8B8G8R8_SINT_PACK32 |
| }; |
| |
| // astc formats have diferent block sizes and thus require diferent resolutions for images |
| enum class AstcImageSizeType |
| { |
| SIZE_64_64 = 0, |
| SIZE_60_64, |
| SIZE_64_60, |
| SIZE_60_60, |
| }; |
| |
| const std::map<VkFormat, AstcImageSizeType> astcSizes |
| { |
| { VK_FORMAT_ASTC_4x4_SRGB_BLOCK, AstcImageSizeType::SIZE_64_64 }, |
| { VK_FORMAT_ASTC_4x4_UNORM_BLOCK, AstcImageSizeType::SIZE_64_64 }, |
| { VK_FORMAT_ASTC_5x4_SRGB_BLOCK, AstcImageSizeType::SIZE_60_64 }, |
| { VK_FORMAT_ASTC_5x4_UNORM_BLOCK, AstcImageSizeType::SIZE_60_64 }, |
| { VK_FORMAT_ASTC_5x5_SRGB_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_5x5_UNORM_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_6x5_SRGB_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_6x5_UNORM_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_6x6_SRGB_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_6x6_UNORM_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_8x5_SRGB_BLOCK, AstcImageSizeType::SIZE_64_60 }, |
| { VK_FORMAT_ASTC_8x5_UNORM_BLOCK, AstcImageSizeType::SIZE_64_60 }, |
| { VK_FORMAT_ASTC_8x6_SRGB_BLOCK, AstcImageSizeType::SIZE_64_60 }, |
| { VK_FORMAT_ASTC_8x6_UNORM_BLOCK, AstcImageSizeType::SIZE_64_60 }, |
| { VK_FORMAT_ASTC_8x8_SRGB_BLOCK, AstcImageSizeType::SIZE_64_64 }, |
| { VK_FORMAT_ASTC_8x8_UNORM_BLOCK, AstcImageSizeType::SIZE_64_64 }, |
| { VK_FORMAT_ASTC_10x5_SRGB_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_10x5_UNORM_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_10x6_SRGB_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_10x6_UNORM_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_10x8_SRGB_BLOCK, AstcImageSizeType::SIZE_60_64 }, |
| { VK_FORMAT_ASTC_10x8_UNORM_BLOCK, AstcImageSizeType::SIZE_60_64 }, |
| { VK_FORMAT_ASTC_10x10_SRGB_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_10x10_UNORM_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_12x10_SRGB_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_12x10_UNORM_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_12x12_SRGB_BLOCK, AstcImageSizeType::SIZE_60_60 }, |
| { VK_FORMAT_ASTC_12x12_UNORM_BLOCK, AstcImageSizeType::SIZE_60_60 } |
| }; |
| |
| std::vector<CopyRegion> create2DCopyRegions(deInt32 srcWidth, deInt32 srcHeight, deInt32 dstWidth, deInt32 dstHeight) |
| { |
| CopyRegion region; |
| std::vector<CopyRegion> regionsVector; |
| |
| deInt32 fourthOfSrcWidth = srcWidth / 4; |
| deInt32 fourthOfSrcHeight = srcHeight / 4; |
| deInt32 fourthOfDstWidth = dstWidth / 4; |
| deInt32 fourthOfDstHeight = dstHeight / 4; |
| |
| // to the top of resulting image copy whole source image but with increasingly smaller sizes |
| for (int i = 0, j = 1; (i + fourthOfDstWidth / j < dstWidth) && (fourthOfDstWidth > j); i += fourthOfDstWidth / j++) |
| { |
| region.imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {srcWidth, srcHeight, 1} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {i, 0, 0}, |
| {i + fourthOfDstWidth / j, fourthOfDstHeight / j, 1} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| regionsVector.push_back(region); |
| } |
| |
| // to the bottom of resulting image copy parts of source image; |
| for (int i = 0; i < 4; ++i) |
| { |
| int srcX = i * fourthOfSrcWidth; |
| int srcY = i * fourthOfSrcHeight; |
| int dstX = i * fourthOfDstWidth; |
| |
| region.imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {srcX, srcY, 0}, |
| {srcX + fourthOfSrcWidth, srcY + fourthOfSrcHeight, 1} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {dstX, 2 * fourthOfDstHeight, 0}, |
| {dstX + fourthOfDstWidth, 3 * fourthOfDstHeight, 1} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| |
| regionsVector.push_back(region); |
| } |
| |
| return regionsVector; |
| } |
| |
| void addBlittingImageAllFormatsColorTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| const struct { |
| const VkFormat* sourceFormats; |
| const VkFormat* destinationFormats; |
| const bool onlyNearest; |
| } colorImageFormatsToTestBlit[] = |
| { |
| { compatibleFormatsUInts, compatibleFormatsUInts, true }, |
| { compatibleFormatsSInts, compatibleFormatsSInts, true }, |
| { compatibleFormatsFloats, compatibleFormatsFloats, false }, |
| { compressedFormatsFloats, compatibleFormatsFloats, false }, |
| { compatibleFormatsSrgb, compatibleFormatsSrgb, false }, |
| { compressedFormatsSrgb, compatibleFormatsSrgb, false }, |
| }; |
| |
| const int numOfColorImageFormatsToTest = DE_LENGTH_OF_ARRAY(colorImageFormatsToTestBlit); |
| |
| if (allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| const int numOfColorImageFormatsToTestFilter = DE_LENGTH_OF_ARRAY(dedicatedAllocationBlittingFormatsToTest); |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTestFilter; ++compatibleFormatsIndex) |
| dedicatedAllocationBlittingFormatsToTestSet.insert(dedicatedAllocationBlittingFormatsToTest[compatibleFormatsIndex]); |
| } |
| |
| // 2D tests. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "2d", "2D blitting tests")); |
| |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.extent = defaultExtent; |
| params.dst.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| // create all required copy regions |
| const std::map<AstcImageSizeType, std::vector<CopyRegion> > imageRegions |
| { |
| { AstcImageSizeType::SIZE_64_64, create2DCopyRegions(64, 64, 64, 64) }, |
| { AstcImageSizeType::SIZE_60_64, create2DCopyRegions(60, 64, 60, 64) }, |
| { AstcImageSizeType::SIZE_64_60, create2DCopyRegions(64, 60, 64, 60) }, |
| { AstcImageSizeType::SIZE_60_60, create2DCopyRegions(60, 60, 60, 60) }, |
| }; |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex) |
| { |
| const VkFormat* sourceFormats = colorImageFormatsToTestBlit[compatibleFormatsIndex].sourceFormats; |
| const VkFormat* destinationFormats = colorImageFormatsToTestBlit[compatibleFormatsIndex].destinationFormats; |
| const bool onlyNearest = colorImageFormatsToTestBlit[compatibleFormatsIndex].onlyNearest; |
| for (int srcFormatIndex = 0; sourceFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex) |
| { |
| VkFormat srcFormat = sourceFormats[srcFormatIndex]; |
| params.src.image.format = srcFormat; |
| |
| const bool onlyNearestAndLinear = de::contains(onlyNearestAndLinearFormatsToTest, params.src.image.format); |
| |
| // most of tests are using regions caluculated for 64x64 size but astc formats require custom regions |
| params.regions = imageRegions.at(AstcImageSizeType::SIZE_64_64); |
| if (isCompressedFormat(srcFormat) && isAstcFormat(mapVkCompressedFormat(srcFormat))) |
| params.regions = imageRegions.at(astcSizes.at(srcFormat)); |
| |
| // use the fact that first region contains the size of full source image |
| // and make source and destination the same size - this is needed for astc formats |
| const VkOffset3D& srcImageSize = params.regions[0].imageBlit.srcOffsets[1]; |
| VkExtent3D& srcImageExtent = params.src.image.extent; |
| VkExtent3D& dstImageExtent = params.dst.image.extent; |
| srcImageExtent.width = srcImageSize.x; |
| srcImageExtent.height = srcImageSize.y; |
| dstImageExtent.width = srcImageSize.x; |
| dstImageExtent.height = srcImageSize.y; |
| |
| BlitColorTestParams testParams |
| { |
| params, |
| destinationFormats, |
| makeFilterMask(onlyNearest, onlyNearestAndLinear) |
| }; |
| |
| const std::string description = "Blit source format " + getFormatCaseName(params.src.image.format); |
| addTestGroup(subGroup.get(), getFormatCaseName(params.src.image.format), description, addBlittingImageAllFormatsColorSrcFormatTests, testParams); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| |
| // 1D tests. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "1d", "1D blitting tests")); |
| |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_1D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_1D; |
| params.src.image.extent = default1dExtent; |
| params.dst.image.extent = default1dExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| CopyRegion region; |
| for (int i = 0; i < defaultSize; i += defaultSize / 2) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize, 1, 1} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {i, 0, 0}, |
| {i + defaultFourthSize, 1, 1} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultFourthSize, 1, 1} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {defaultFourthSize, 0, 0}, |
| {2 * defaultFourthSize, 1, 1} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex) |
| { |
| const VkFormat* sourceFormats = colorImageFormatsToTestBlit[compatibleFormatsIndex].sourceFormats; |
| const bool onlyNearest = colorImageFormatsToTestBlit[compatibleFormatsIndex].onlyNearest; |
| for (int srcFormatIndex = 0; sourceFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex) |
| { |
| params.src.image.format = sourceFormats[srcFormatIndex]; |
| if (!isSupportedByFramework(params.src.image.format)) |
| continue; |
| |
| // Cubic filtering can only be used with 2D images. |
| const bool onlyNearestAndLinear = true; |
| |
| BlitColorTestParams testParams |
| { |
| params, |
| nullptr, |
| makeFilterMask(onlyNearest, onlyNearestAndLinear) |
| }; |
| |
| const std::string description = "Blit source format " + getFormatCaseName(params.src.image.format); |
| addTestGroup(subGroup.get(), getFormatCaseName(params.src.image.format), description, addBlittingImageAllFormatsColorSrcFormatTests, testParams); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| |
| // 3D tests. Note we use smaller dimensions here for performance reasons. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "3d", "3D blitting tests")); |
| |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_3D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_3D; |
| params.src.image.extent = default3dExtent; |
| params.dst.image.extent = default3dExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| CopyRegion region; |
| for (int i = 0, j = 1; (i + defaultSixteenthSize / j < defaultFourthSize) && (defaultSixteenthSize > j); i += defaultSixteenthSize / j++) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultFourthSize, defaultFourthSize, defaultFourthSize} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {i, 0, i}, |
| {i + defaultSixteenthSize / j, defaultSixteenthSize / j, i + defaultSixteenthSize / j} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| for (int i = 0; i < defaultFourthSize; i += defaultSixteenthSize) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {i, i, i}, |
| {i + defaultSixteenthSize, i + defaultSixteenthSize, i + defaultSixteenthSize} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| defaultSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {i, defaultFourthSize / 2, i}, |
| {i + defaultSixteenthSize, defaultFourthSize / 2 + defaultSixteenthSize, i + defaultSixteenthSize} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex) |
| { |
| const VkFormat* sourceFormats = colorImageFormatsToTestBlit[compatibleFormatsIndex].sourceFormats; |
| const bool onlyNearest = colorImageFormatsToTestBlit[compatibleFormatsIndex].onlyNearest; |
| for (int srcFormatIndex = 0; sourceFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex) |
| { |
| params.src.image.format = sourceFormats[srcFormatIndex]; |
| if (!isSupportedByFramework(params.src.image.format)) |
| continue; |
| |
| // Cubic filtering can only be used with 2D images. |
| const bool onlyNearestAndLinear = true; |
| |
| BlitColorTestParams testParams |
| { |
| params, |
| nullptr, |
| makeFilterMask(onlyNearest, onlyNearestAndLinear) |
| }; |
| |
| const std::string description = "Blit source format " + getFormatCaseName(params.src.image.format); |
| addTestGroup(subGroup.get(), getFormatCaseName(params.src.image.format), description, addBlittingImageAllFormatsColorSrcFormatTests, testParams); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| } |
| |
| void addBlittingImageAllFormatsDepthStencilFormatsTests (tcu::TestCaseGroup* group, TestParams params) |
| { |
| const VkImageLayout blitSrcLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| const VkImageLayout blitDstLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| |
| for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(blitSrcLayouts); ++srcLayoutNdx) |
| { |
| params.src.image.operationLayout = blitSrcLayouts[srcLayoutNdx]; |
| |
| for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(blitDstLayouts); ++dstLayoutNdx) |
| { |
| params.dst.image.operationLayout = blitDstLayouts[dstLayoutNdx]; |
| params.filter = VK_FILTER_NEAREST; |
| |
| const std::string testName = getImageLayoutCaseName(params.src.image.operationLayout) + "_" + |
| getImageLayoutCaseName(params.dst.image.operationLayout); |
| const std::string description = "Blit from " + getImageLayoutCaseName(params.src.image.operationLayout) + |
| " to " + getImageLayoutCaseName(params.dst.image.operationLayout); |
| |
| group->addChild(new BlitImageTestCase(group->getTestContext(), testName + "_nearest", description, params)); |
| } |
| } |
| } |
| |
| void addBlittingImageAllFormatsDepthStencilTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| const VkFormat depthAndStencilFormats[] = |
| { |
| VK_FORMAT_D16_UNORM, |
| VK_FORMAT_X8_D24_UNORM_PACK32, |
| VK_FORMAT_D32_SFLOAT, |
| VK_FORMAT_S8_UINT, |
| VK_FORMAT_D16_UNORM_S8_UINT, |
| VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_FORMAT_D32_SFLOAT_S8_UINT, |
| }; |
| |
| const VkImageSubresourceLayers defaultDepthSourceLayer = { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, 1u }; |
| const VkImageSubresourceLayers defaultStencilSourceLayer = { VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u }; |
| const VkImageSubresourceLayers defaultDSSourceLayer = { VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u }; |
| |
| // 2D tests |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "2d", "2D blitting tests")); |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(depthAndStencilFormats); ++compatibleFormatsIndex) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.format = depthAndStencilFormats[compatibleFormatsIndex]; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = params.src.image.format; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| params.separateDepthStencilLayouts = DE_FALSE; |
| |
| bool hasDepth = tcu::hasDepthComponent(mapVkFormat(params.src.image.format).order); |
| bool hasStencil = tcu::hasStencilComponent(mapVkFormat(params.src.image.format).order); |
| |
| CopyRegion region; |
| for (int i = 0, j = 1; (i + defaultFourthSize / j < defaultSize) && (defaultFourthSize > j); i += defaultFourthSize / j++) |
| { |
| const VkOffset3D srcOffset0 = {0, 0, 0}; |
| const VkOffset3D srcOffset1 = {defaultSize, defaultSize, 1}; |
| const VkOffset3D dstOffset0 = {i, 0, 0}; |
| const VkOffset3D dstOffset1 = {i + defaultFourthSize / j, defaultFourthSize / j, 1}; |
| |
| if (hasDepth) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultDepthSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0 , srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultDepthSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0 , dstOffset1 }, // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| if (hasStencil) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultStencilSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0 , srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultStencilSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0 , dstOffset1 }, // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| } |
| for (int i = 0; i < defaultSize; i += defaultFourthSize) |
| { |
| const VkOffset3D srcOffset0 = {i, i, 0}; |
| const VkOffset3D srcOffset1 = {i + defaultFourthSize, i + defaultFourthSize, 1}; |
| const VkOffset3D dstOffset0 = {i, defaultSize / 2, 0}; |
| const VkOffset3D dstOffset1 = {i + defaultFourthSize, defaultSize / 2 + defaultFourthSize, 1}; |
| |
| if (hasDepth) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultDepthSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0, srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultDepthSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0, dstOffset1 } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| if (hasStencil) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultStencilSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0, srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultStencilSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0, dstOffset1 } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| if (hasDepth && hasStencil) |
| { |
| const VkOffset3D dstDSOffset0 = {i, 3 * defaultFourthSize, 0}; |
| const VkOffset3D dstDSOffset1 = {i + defaultFourthSize, defaultSize, 1}; |
| const VkImageBlit imageBlit = |
| { |
| defaultDSSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0, srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultDSSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstDSOffset0, dstDSOffset1 } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| } |
| |
| const std::string testName = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format); |
| const std::string description = "Blit from " + getFormatCaseName(params.src.image.format) + |
| " to " + getFormatCaseName(params.dst.image.format); |
| addTestGroup(subGroup.get(), testName, description, addBlittingImageAllFormatsDepthStencilFormatsTests, params); |
| |
| if (hasDepth && hasStencil) |
| { |
| params.separateDepthStencilLayouts = DE_TRUE; |
| const std::string testName2 = getFormatCaseName(params.src.image.format) + "_" + |
| getFormatCaseName(params.dst.image.format) + "_separate_layouts"; |
| const std::string description2 = "Blit from " + getFormatCaseName(params.src.image.format) + |
| " to " + getFormatCaseName(params.dst.image.format) + " with separate depth/stencil layouts"; |
| addTestGroup(subGroup.get(), testName2, description2, addBlittingImageAllFormatsDepthStencilFormatsTests, params); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| |
| // 1D tests |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "1d", "1D blitting tests")); |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(depthAndStencilFormats); ++compatibleFormatsIndex) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_1D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_1D; |
| params.src.image.extent = default1dExtent; |
| params.dst.image.extent = default1dExtent; |
| params.src.image.format = depthAndStencilFormats[compatibleFormatsIndex]; |
| params.dst.image.format = params.src.image.format; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| bool hasDepth = tcu::hasDepthComponent(mapVkFormat(params.src.image.format).order); |
| bool hasStencil = tcu::hasStencilComponent(mapVkFormat(params.src.image.format).order); |
| |
| CopyRegion region; |
| for (int i = 0; i < defaultSize; i += defaultSize / 2) |
| { |
| const VkOffset3D srcOffset0 = {0, 0, 0}; |
| const VkOffset3D srcOffset1 = {defaultSize, 1, 1}; |
| const VkOffset3D dstOffset0 = {i, 0, 0}; |
| const VkOffset3D dstOffset1 = {i + defaultFourthSize, 1, 1}; |
| |
| if (hasDepth) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultDepthSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0 , srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultDepthSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0 , dstOffset1 }, // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| if (hasStencil) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultStencilSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0 , srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultStencilSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0 , dstOffset1 }, // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| } |
| |
| { |
| const VkOffset3D srcOffset0 = {0, 0, 0}; |
| const VkOffset3D srcOffset1 = {defaultFourthSize, 1, 1}; |
| const VkOffset3D dstOffset0 = {defaultFourthSize, 0, 0}; |
| const VkOffset3D dstOffset1 = {2 * defaultFourthSize, 1, 1}; |
| |
| if (hasDepth) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultDepthSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0, srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultDepthSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0, dstOffset1 } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| if (hasStencil) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultStencilSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0, srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultStencilSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0, dstOffset1 } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| if (hasDepth && hasStencil) |
| { |
| const VkOffset3D dstDSOffset0 = {3 * defaultFourthSize, 0, 0}; |
| const VkOffset3D dstDSOffset1 = {3 * defaultFourthSize + defaultFourthSize / 2, 1, 1}; |
| const VkImageBlit imageBlit = |
| { |
| defaultDSSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0, srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultDSSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstDSOffset0, dstDSOffset1 } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| } |
| |
| const std::string testName = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format); |
| const std::string description = "Blit from " + getFormatCaseName(params.src.image.format) + |
| " to " + getFormatCaseName(params.dst.image.format); |
| addTestGroup(subGroup.get(), testName, description, addBlittingImageAllFormatsDepthStencilFormatsTests, params); |
| |
| if (hasDepth && hasStencil) |
| { |
| params.separateDepthStencilLayouts = DE_TRUE; |
| const std::string testName2 = getFormatCaseName(params.src.image.format) + "_" + |
| getFormatCaseName(params.dst.image.format) + "_separate_layouts"; |
| const std::string description2 = "Blit from " + getFormatCaseName(params.src.image.format) + |
| " to " + getFormatCaseName(params.dst.image.format) + " with separate depth/stencil layouts"; |
| addTestGroup(subGroup.get(), testName2, description2, addBlittingImageAllFormatsDepthStencilFormatsTests, params); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| |
| // 3D tests. Note we use smaller dimensions here for performance reasons. |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "3d", "3D blitting tests")); |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(depthAndStencilFormats); ++compatibleFormatsIndex) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_3D; |
| params.dst.image.imageType = VK_IMAGE_TYPE_3D; |
| params.src.image.extent = default3dExtent; |
| params.dst.image.extent = default3dExtent; |
| params.src.image.format = depthAndStencilFormats[compatibleFormatsIndex]; |
| params.dst.image.format = params.src.image.format; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| bool hasDepth = tcu::hasDepthComponent(mapVkFormat(params.src.image.format).order); |
| bool hasStencil = tcu::hasStencilComponent(mapVkFormat(params.src.image.format).order); |
| |
| CopyRegion region; |
| for (int i = 0, j = 1; (i + defaultSixteenthSize / j < defaultFourthSize) && (defaultSixteenthSize > j); i += defaultSixteenthSize / j++) |
| { |
| const VkOffset3D srcOffset0 = {0, 0, 0}; |
| const VkOffset3D srcOffset1 = {defaultFourthSize, defaultFourthSize, defaultFourthSize}; |
| const VkOffset3D dstOffset0 = {i, 0, i}; |
| const VkOffset3D dstOffset1 = {i + defaultSixteenthSize / j, defaultSixteenthSize / j, i + defaultSixteenthSize / j}; |
| |
| if (hasDepth) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultDepthSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0 , srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultDepthSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0 , dstOffset1 }, // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| if (hasStencil) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultStencilSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0 , srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultStencilSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0 , dstOffset1 }, // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| } |
| for (int i = 0; i < defaultFourthSize; i += defaultSixteenthSize) |
| { |
| const VkOffset3D srcOffset0 = {i, i, i}; |
| const VkOffset3D srcOffset1 = {i + defaultSixteenthSize, i + defaultSixteenthSize, i + defaultSixteenthSize}; |
| const VkOffset3D dstOffset0 = {i, defaultFourthSize / 2, i}; |
| const VkOffset3D dstOffset1 = {i + defaultSixteenthSize, defaultFourthSize / 2 + defaultSixteenthSize, i + defaultSixteenthSize}; |
| |
| if (hasDepth) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultDepthSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0, srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultDepthSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0, dstOffset1 } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| if (hasStencil) |
| { |
| const VkImageBlit imageBlit = |
| { |
| defaultStencilSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0, srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultStencilSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstOffset0, dstOffset1 } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| if (hasDepth && hasStencil) |
| { |
| const VkOffset3D dstDSOffset0 = {i, 3 * defaultSixteenthSize, i}; |
| const VkOffset3D dstDSOffset1 = {i + defaultSixteenthSize, defaultFourthSize, i + defaultSixteenthSize}; |
| const VkImageBlit imageBlit = |
| { |
| defaultDSSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { srcOffset0, srcOffset1 }, // VkOffset3D srcOffsets[2]; |
| defaultDSSourceLayer, // VkImageSubresourceLayers dstSubresource; |
| { dstDSOffset0, dstDSOffset1 } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| } |
| |
| const std::string testName = getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format); |
| const std::string description = "Blit from " + getFormatCaseName(params.src.image.format) + |
| " to " + getFormatCaseName(params.dst.image.format); |
| addTestGroup(subGroup.get(), testName, description, addBlittingImageAllFormatsDepthStencilFormatsTests, params); |
| |
| if (hasDepth && hasStencil) |
| { |
| params.separateDepthStencilLayouts = DE_TRUE; |
| const std::string testName2 = getFormatCaseName(params.src.image.format) + "_" + |
| getFormatCaseName(params.dst.image.format) + "_separate_layouts"; |
| const std::string description2 = "Blit from " + getFormatCaseName(params.src.image.format) + |
| " to " + getFormatCaseName(params.dst.image.format) + " with separate depth/stencil layouts"; |
| addTestGroup(subGroup.get(), testName2, description2, addBlittingImageAllFormatsDepthStencilFormatsTests, params); |
| } |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| } |
| |
| void addBlittingImageAllFormatsMipmapFormatTests (tcu::TestCaseGroup* group, BlitColorTestParams testParams) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| const VkImageLayout blitSrcLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| const VkImageLayout blitDstLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| VK_IMAGE_LAYOUT_GENERAL |
| }; |
| |
| for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(blitSrcLayouts); ++srcLayoutNdx) |
| { |
| testParams.params.src.image.operationLayout = blitSrcLayouts[srcLayoutNdx]; |
| for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(blitDstLayouts); ++dstLayoutNdx) |
| { |
| testParams.params.dst.image.operationLayout = blitDstLayouts[dstLayoutNdx]; |
| |
| testParams.params.filter = VK_FILTER_NEAREST; |
| const std::string testName = getImageLayoutCaseName(testParams.params.src.image.operationLayout) + "_" + |
| getImageLayoutCaseName(testParams.params.dst.image.operationLayout); |
| const std::string description = "Blit from layout " + getImageLayoutCaseName(testParams.params.src.image.operationLayout) + |
| " to " + getImageLayoutCaseName(testParams.params.dst.image.operationLayout); |
| group->addChild(new BlitMipmapTestCase(testCtx, testName + "_nearest", description, testParams.params)); |
| |
| if (testParams.testFilters & FILTER_MASK_LINEAR) |
| { |
| testParams.params.filter = VK_FILTER_LINEAR; |
| group->addChild(new BlitMipmapTestCase(testCtx, testName + "_linear", description, testParams.params)); |
| } |
| |
| if (testParams.testFilters & FILTER_MASK_CUBIC) |
| { |
| testParams.params.filter = VK_FILTER_CUBIC_EXT; |
| group->addChild(new BlitMipmapTestCase(testCtx, testName + "_cubic", description, testParams.params)); |
| } |
| } |
| } |
| } |
| |
| void addBlittingImageAllFormatsBaseLevelMipmapTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| const struct |
| { |
| const VkFormat* const compatibleFormats; |
| const bool onlyNearest; |
| } colorImageFormatsToTestBlit[] = |
| { |
| { compatibleFormatsUInts, true }, |
| { compatibleFormatsSInts, true }, |
| { compatibleFormatsFloats, false }, |
| { compatibleFormatsSrgb, false }, |
| }; |
| |
| const int numOfColorImageFormatsToTest = DE_LENGTH_OF_ARRAY(colorImageFormatsToTestBlit); |
| |
| const int layerCountsToTest[] = |
| { |
| 1, |
| 6 |
| }; |
| |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| params.mipLevels = deLog2Floor32(deMinu32(defaultExtent.width, defaultExtent.height)) + 1u; |
| params.singleCommand = DE_TRUE; |
| |
| CopyRegion region; |
| for (deUint32 mipLevelNdx = 0u; mipLevelNdx < params.mipLevels; mipLevelNdx++) |
| { |
| VkImageSubresourceLayers destLayer = defaultSourceLayer; |
| destLayer.mipLevel = mipLevelNdx; |
| |
| const VkImageBlit imageBlit = |
| { |
| defaultSourceLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize, defaultSize, 1} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| destLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize >> mipLevelNdx, defaultSize >> mipLevelNdx, 1} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| if (allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| const int numOfColorImageFormatsToTestFilter = DE_LENGTH_OF_ARRAY(dedicatedAllocationBlittingFormatsToTest); |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTestFilter; ++compatibleFormatsIndex) |
| dedicatedAllocationBlittingFormatsToTestSet.insert(dedicatedAllocationBlittingFormatsToTest[compatibleFormatsIndex]); |
| } |
| |
| for (int layerCountIndex = 0; layerCountIndex < DE_LENGTH_OF_ARRAY(layerCountsToTest); layerCountIndex++) |
| { |
| const int layerCount = layerCountsToTest[layerCountIndex]; |
| const std::string layerGroupName = "layercount_" + de::toString(layerCount); |
| const std::string layerGroupDesc = "Blit mipmaps with layerCount = " + de::toString(layerCount); |
| |
| de::MovePtr<tcu::TestCaseGroup> layerCountGroup (new tcu::TestCaseGroup(group->getTestContext(), layerGroupName.c_str(), layerGroupDesc.c_str())); |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex) |
| { |
| const VkFormat* compatibleFormats = colorImageFormatsToTestBlit[compatibleFormatsIndex].compatibleFormats; |
| const bool onlyNearest = colorImageFormatsToTestBlit[compatibleFormatsIndex].onlyNearest; |
| |
| for (int srcFormatIndex = 0; compatibleFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex) |
| { |
| params.src.image.format = compatibleFormats[srcFormatIndex]; |
| params.dst.image.format = compatibleFormats[srcFormatIndex]; |
| |
| if (!isSupportedByFramework(params.src.image.format)) |
| continue; |
| |
| const bool onlyNearestAndLinear = de::contains(onlyNearestAndLinearFormatsToTest, params.src.image.format); |
| |
| const std::string description = "Blit source format " + getFormatCaseName(params.src.image.format); |
| |
| BlitColorTestParams testParams; |
| testParams.params = params; |
| testParams.compatibleFormats = compatibleFormats; |
| testParams.testFilters = makeFilterMask(onlyNearest, onlyNearestAndLinear); |
| |
| testParams.params.src.image.extent.depth = layerCount; |
| testParams.params.dst.image.extent.depth = layerCount; |
| |
| for (size_t regionNdx = 0; regionNdx < testParams.params.regions.size(); regionNdx++) |
| { |
| testParams.params.regions[regionNdx].imageBlit.srcSubresource.layerCount = layerCount; |
| testParams.params.regions[regionNdx].imageBlit.dstSubresource.layerCount = layerCount; |
| } |
| |
| addTestGroup(layerCountGroup.get(), getFormatCaseName(params.src.image.format), description, addBlittingImageAllFormatsMipmapFormatTests, testParams); |
| } |
| } |
| group->addChild(layerCountGroup.release()); |
| } |
| } |
| |
| void addBlittingImageAllFormatsPreviousLevelMipmapTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| const struct |
| { |
| const VkFormat* const compatibleFormats; |
| const bool onlyNearest; |
| } colorImageFormatsToTestBlit[] = |
| { |
| { compatibleFormatsUInts, true }, |
| { compatibleFormatsSInts, true }, |
| { compatibleFormatsFloats, false }, |
| { compatibleFormatsSrgb, false }, |
| }; |
| |
| const int numOfColorImageFormatsToTest = DE_LENGTH_OF_ARRAY(colorImageFormatsToTestBlit); |
| |
| const int layerCountsToTest[] = |
| { |
| 1, |
| 6 |
| }; |
| |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| params.mipLevels = deLog2Floor32(deMinu32(defaultExtent.width, defaultExtent.height)) + 1u; |
| params.singleCommand = DE_FALSE; |
| |
| CopyRegion region; |
| for (deUint32 mipLevelNdx = 1u; mipLevelNdx < params.mipLevels; mipLevelNdx++) |
| { |
| VkImageSubresourceLayers srcLayer = defaultSourceLayer; |
| VkImageSubresourceLayers destLayer = defaultSourceLayer; |
| |
| srcLayer.mipLevel = mipLevelNdx - 1u; |
| destLayer.mipLevel = mipLevelNdx; |
| |
| const VkImageBlit imageBlit = |
| { |
| srcLayer, // VkImageSubresourceLayers srcSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize >> (mipLevelNdx - 1u), defaultSize >> (mipLevelNdx - 1u), 1} |
| }, // VkOffset3D srcOffsets[2]; |
| |
| destLayer, // VkImageSubresourceLayers dstSubresource; |
| { |
| {0, 0, 0}, |
| {defaultSize >> mipLevelNdx, defaultSize >> mipLevelNdx, 1} |
| } // VkOffset3D dstOffset[2]; |
| }; |
| region.imageBlit = imageBlit; |
| params.regions.push_back(region); |
| } |
| |
| if (allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| const int numOfColorImageFormatsToTestFilter = DE_LENGTH_OF_ARRAY(dedicatedAllocationBlittingFormatsToTest); |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTestFilter; ++compatibleFormatsIndex) |
| dedicatedAllocationBlittingFormatsToTestSet.insert(dedicatedAllocationBlittingFormatsToTest[compatibleFormatsIndex]); |
| } |
| |
| for (int layerCountIndex = 0; layerCountIndex < DE_LENGTH_OF_ARRAY(layerCountsToTest); layerCountIndex++) |
| { |
| const int layerCount = layerCountsToTest[layerCountIndex]; |
| const std::string layerGroupName = "layercount_" + de::toString(layerCount); |
| const std::string layerGroupDesc = "Blit mipmaps with layerCount = " + de::toString(layerCount); |
| |
| de::MovePtr<tcu::TestCaseGroup> layerCountGroup (new tcu::TestCaseGroup(group->getTestContext(), layerGroupName.c_str(), layerGroupDesc.c_str())); |
| |
| for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex) |
| { |
| const VkFormat* compatibleFormats = colorImageFormatsToTestBlit[compatibleFormatsIndex].compatibleFormats; |
| const bool onlyNearest = colorImageFormatsToTestBlit[compatibleFormatsIndex].onlyNearest; |
| |
| for (int srcFormatIndex = 0; compatibleFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex) |
| { |
| params.src.image.format = compatibleFormats[srcFormatIndex]; |
| params.dst.image.format = compatibleFormats[srcFormatIndex]; |
| |
| if (!isSupportedByFramework(params.src.image.format)) |
| continue; |
| |
| const bool onlyNearestAndLinear = de::contains(onlyNearestAndLinearFormatsToTest, params.src.image.format); |
| |
| const std::string description = "Blit source format " + getFormatCaseName(params.src.image.format); |
| |
| BlitColorTestParams testParams; |
| testParams.params = params; |
| testParams.compatibleFormats = compatibleFormats; |
| testParams.testFilters = makeFilterMask(onlyNearest, onlyNearestAndLinear); |
| |
| testParams.params.src.image.extent.depth = layerCount; |
| testParams.params.dst.image.extent.depth = layerCount; |
| |
| for (size_t regionNdx = 0; regionNdx < testParams.params.regions.size(); regionNdx++) |
| { |
| testParams.params.regions[regionNdx].imageBlit.srcSubresource.layerCount = layerCount; |
| testParams.params.regions[regionNdx].imageBlit.dstSubresource.layerCount = layerCount; |
| } |
| |
| addTestGroup(layerCountGroup.get(), getFormatCaseName(params.src.image.format), description, addBlittingImageAllFormatsMipmapFormatTests, testParams); |
| } |
| } |
| group->addChild(layerCountGroup.release()); |
| } |
| |
| for (int multiLayer = 0; multiLayer < 2; multiLayer++) |
| { |
| const int layerCount = multiLayer ? 6 : 1; |
| |
| for (int barrierCount = 1; barrierCount < 4; barrierCount++) |
| { |
| if (layerCount != 1 || barrierCount != 1) |
| { |
| const std::string barrierGroupName = (multiLayer ? "layerbarriercount_" : "mipbarriercount_") + de::toString(barrierCount); |
| const std::string barrierGroupDesc = "Use " + de::toString(barrierCount) + " image barriers"; |
| |
| de::MovePtr<tcu::TestCaseGroup> barrierCountGroup(new tcu::TestCaseGroup(group->getTestContext(), barrierGroupName.c_str(), barrierGroupDesc.c_str())); |
| |
| params.barrierCount = barrierCount; |
| |
| // Only go through a few common formats |
| for (int srcFormatIndex = 2; srcFormatIndex < 6; ++srcFormatIndex) |
| { |
| params.src.image.format = compatibleFormatsUInts[srcFormatIndex]; |
| params.dst.image.format = compatibleFormatsUInts[srcFormatIndex]; |
| |
| if (!isSupportedByFramework(params.src.image.format)) |
| continue; |
| |
| const std::string description = "Blit source format " + getFormatCaseName(params.src.image.format); |
| |
| BlitColorTestParams testParams; |
| testParams.params = params; |
| testParams.compatibleFormats = compatibleFormatsUInts; |
| testParams.testFilters = FILTER_MASK_NEAREST; |
| |
| testParams.params.src.image.extent.depth = layerCount; |
| testParams.params.dst.image.extent.depth = layerCount; |
| |
| for (size_t regionNdx = 0; regionNdx < testParams.params.regions.size(); regionNdx++) |
| { |
| testParams.params.regions[regionNdx].imageBlit.srcSubresource.layerCount = layerCount; |
| testParams.params.regions[regionNdx].imageBlit.dstSubresource.layerCount = layerCount; |
| } |
| |
| addTestGroup(barrierCountGroup.get(), getFormatCaseName(params.src.image.format), description, addBlittingImageAllFormatsMipmapFormatTests, testParams); |
| } |
| group->addChild(barrierCountGroup.release()); |
| } |
| } |
| } |
| } |
| |
| void addBlittingImageAllFormatsMipmapTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| addTestGroup(group, "from_base_level", "Generate all mipmap levels from base level", addBlittingImageAllFormatsBaseLevelMipmapTests, allocationKind, extensionUse); |
| addTestGroup(group, "from_previous_level", "Generate next mipmap level from previous level", addBlittingImageAllFormatsPreviousLevelMipmapTests, allocationKind, extensionUse); |
| } |
| |
| void addBlittingImageAllFormatsTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| addTestGroup(group, "color", "Blitting image with color formats", addBlittingImageAllFormatsColorTests, allocationKind, extensionUse); |
| addTestGroup(group, "depth_stencil", "Blitting image with depth/stencil formats", addBlittingImageAllFormatsDepthStencilTests, allocationKind, extensionUse); |
| addTestGroup(group, "generate_mipmaps", "Generating mipmaps with vkCmdBlitImage()", addBlittingImageAllFormatsMipmapTests, allocationKind, extensionUse); |
| } |
| |
| void addBlittingImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| addTestGroup(group, "simple_tests", "Blitting image simple tests", addBlittingImageSimpleTests, allocationKind, extensionUse); |
| addTestGroup(group, "all_formats", "Blitting image with all compatible formats", addBlittingImageAllFormatsTests, allocationKind, extensionUse); |
| } |
| |
| const VkSampleCountFlagBits samples[] = |
| { |
| VK_SAMPLE_COUNT_2_BIT, |
| VK_SAMPLE_COUNT_4_BIT, |
| VK_SAMPLE_COUNT_8_BIT, |
| VK_SAMPLE_COUNT_16_BIT, |
| VK_SAMPLE_COUNT_32_BIT, |
| VK_SAMPLE_COUNT_64_BIT |
| }; |
| const VkExtent3D resolveExtent = {256u, 256u, 1}; |
| |
| void addResolveImageWholeTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = resolveExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = resolveExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| const VkImageResolve testResolve = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| resolveExtent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageResolve; |
| imageResolve.imageResolve = testResolve; |
| params.regions.push_back(imageResolve); |
| } |
| |
| for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex) |
| { |
| params.samples = samples[samplesIndex]; |
| const std::string description = "With " + getSampleCountCaseName(samples[samplesIndex]); |
| group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params)); |
| } |
| } |
| |
| void addResolveImagePartialTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = resolveExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = resolveExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| const VkImageResolve testResolve = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {64u, 64u, 0}, // VkOffset3D dstOffset; |
| {128u, 128u, 1u}, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageResolve; |
| imageResolve.imageResolve = testResolve; |
| params.regions.push_back(imageResolve); |
| } |
| |
| for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex) |
| { |
| params.samples = samples[samplesIndex]; |
| const std::string description = "With " + getSampleCountCaseName(samples[samplesIndex]); |
| group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params)); |
| } |
| } |
| |
| void addResolveImageWithRegionsTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = resolveExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = resolveExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| for (int i = 0; i < 256; i += 64) |
| { |
| const VkImageResolve testResolve = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {i, i, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {i, 0, 0}, // VkOffset3D dstOffset; |
| {64u, 64u, 1u}, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageResolve; |
| imageResolve.imageResolve = testResolve; |
| params.regions.push_back(imageResolve); |
| } |
| } |
| |
| for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex) |
| { |
| params.samples = samples[samplesIndex]; |
| const std::string description = "With " + getSampleCountCaseName(samples[samplesIndex]); |
| group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params)); |
| } |
| } |
| |
| void addResolveImageWholeCopyBeforeResolvingTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageResolve testResolve = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultExtent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageResolve; |
| imageResolve.imageResolve = testResolve; |
| params.regions.push_back(imageResolve); |
| } |
| |
| for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex) |
| { |
| params.samples = samples[samplesIndex]; |
| const std::string description = "With " + getSampleCountCaseName(samples[samplesIndex]); |
| group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params, COPY_MS_IMAGE_TO_MS_IMAGE)); |
| } |
| } |
| |
| void addResolveImageWholeCopyDiffLayoutsBeforeResolvingTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageResolve testResolve = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultExtent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageResolve; |
| imageResolve.imageResolve = testResolve; |
| params.regions.push_back(imageResolve); |
| } |
| |
| const struct |
| { |
| VkImageLayout layout; |
| std::string name; |
| } imageLayouts[] = |
| { |
| { VK_IMAGE_LAYOUT_GENERAL, "general" }, |
| { VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "transfer_src_optimal" }, |
| { VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "transfer_dst_optimal" } |
| }; |
| |
| for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex) |
| for (int srcLayoutIndex = 0; srcLayoutIndex < DE_LENGTH_OF_ARRAY(imageLayouts); ++srcLayoutIndex) |
| for (int dstLayoutIndex = 0; dstLayoutIndex < DE_LENGTH_OF_ARRAY(imageLayouts); ++dstLayoutIndex) |
| { |
| params.src.image.operationLayout = imageLayouts[srcLayoutIndex].layout; |
| params.dst.image.operationLayout = imageLayouts[dstLayoutIndex].layout; |
| if (params.src.image.operationLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL || |
| params.dst.image.operationLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) |
| continue; |
| params.samples = samples[samplesIndex]; |
| const std::string description = "With " + getSampleCountCaseName(samples[samplesIndex]); |
| std::string testName = getSampleCountCaseName(samples[samplesIndex]) + "_" + imageLayouts[srcLayoutIndex].name + "_" + imageLayouts[dstLayoutIndex].name; |
| group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), testName, description, params, COPY_MS_IMAGE_TO_MS_IMAGE)); |
| } |
| } |
| |
| void addResolveImageWholeArrayImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.extent.depth = 5u; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| for (deUint32 layerNdx=0; layerNdx < params.dst.image.extent.depth; ++layerNdx) |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| layerNdx, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| |
| const VkImageResolve testResolve = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultExtent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageResolve; |
| imageResolve.imageResolve = testResolve; |
| params.regions.push_back(imageResolve); |
| } |
| |
| for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex) |
| { |
| params.samples = samples[samplesIndex]; |
| const std::string description = "With " + getSampleCountCaseName(samples[samplesIndex]); |
| group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params, COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE)); |
| } |
| } |
| |
| void addResolveImageWholeArrayImageSingleRegionTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.extent = defaultExtent; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.extent = defaultExtent; |
| params.dst.image.extent.depth = 5u; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // uint32_t mipLevel; |
| 0, // uint32_t baseArrayLayer; |
| params.dst.image.extent.depth // uint32_t layerCount; |
| }; |
| |
| const VkImageResolve testResolve = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| defaultExtent, // VkExtent3D extent; |
| }; |
| |
| CopyRegion imageResolve; |
| imageResolve.imageResolve = testResolve; |
| params.regions.push_back(imageResolve); |
| |
| for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex) |
| { |
| params.samples = samples[samplesIndex]; |
| const std::string description = "With " + getSampleCountCaseName(samples[samplesIndex]); |
| group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params, COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE)); |
| } |
| } |
| |
| void addResolveImageDiffImageSizeTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| TestParams params; |
| params.src.image.imageType = VK_IMAGE_TYPE_2D; |
| params.src.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.src.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.src.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| params.dst.image.imageType = VK_IMAGE_TYPE_2D; |
| params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM; |
| params.dst.image.tiling = VK_IMAGE_TILING_OPTIMAL; |
| params.dst.image.operationLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| params.allocationKind = allocationKind; |
| params.extensionUse = extensionUse; |
| |
| { |
| const VkImageSubresourceLayers sourceLayer = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| }; |
| const VkImageResolve testResolve = |
| { |
| sourceLayer, // VkImageSubresourceLayers srcSubresource; |
| {0, 0, 0}, // VkOffset3D srcOffset; |
| sourceLayer, // VkImageSubresourceLayers dstSubresource; |
| {0, 0, 0}, // VkOffset3D dstOffset; |
| resolveExtent, // VkExtent3D extent; |
| }; |
| CopyRegion imageResolve; |
| imageResolve.imageResolve = testResolve; |
| params.regions.push_back(imageResolve); |
| } |
| |
| const VkExtent3D imageExtents[] = |
| { |
| { resolveExtent.width + 10, resolveExtent.height, resolveExtent.depth }, |
| { resolveExtent.width, resolveExtent.height * 2, resolveExtent.depth }, |
| { resolveExtent.width, resolveExtent.height, resolveExtent.depth + 10 } |
| }; |
| |
| for (int srcImageExtentIndex = 0; srcImageExtentIndex < DE_LENGTH_OF_ARRAY(imageExtents); ++srcImageExtentIndex) |
| { |
| const VkExtent3D& srcImageSize = imageExtents[srcImageExtentIndex]; |
| params.src.image.extent = srcImageSize; |
| params.dst.image.extent = resolveExtent; |
| for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex) |
| { |
| params.samples = samples[samplesIndex]; |
| std::ostringstream testName; |
| testName << "src_" << srcImageSize.width << "_" << srcImageSize.height << "_" << srcImageSize.depth << "_" << getSampleCountCaseName(samples[samplesIndex]); |
| std::ostringstream description; |
| description << "With " << getSampleCountCaseName(samples[samplesIndex]) << " and source image size (" |
| << srcImageSize.width << ", " << srcImageSize.height << ", " << srcImageSize.depth << ")"; |
| group->addChild(new ResolveImageToImageTestCase(testCtx, testName.str(), description.str(), params)); |
| } |
| } |
| for (int dstImageExtentIndex = 0; dstImageExtentIndex < DE_LENGTH_OF_ARRAY(imageExtents); ++dstImageExtentIndex) |
| { |
| const VkExtent3D& dstImageSize = imageExtents[dstImageExtentIndex]; |
| params.src.image.extent = resolveExtent; |
| params.dst.image.extent = dstImageSize; |
| for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex) |
| { |
| params.samples = samples[samplesIndex]; |
| std::ostringstream testName; |
| testName << "dst_" << dstImageSize.width << "_" << dstImageSize.height << "_" << dstImageSize.depth << "_" << getSampleCountCaseName(samples[samplesIndex]); |
| std::ostringstream description; |
| description << "With " << getSampleCountCaseName(samples[samplesIndex]) << " and destination image size (" |
| << dstImageSize.width << ", " << dstImageSize.height << ", " << dstImageSize.depth << ")"; |
| group->addChild(new ResolveImageToImageTestCase(testCtx, testName.str(), description.str(), params)); |
| } |
| } |
| } |
| |
| void addBufferCopyOffsetTests (tcu::TestCaseGroup* group) |
| { |
| de::MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(group->getTestContext(), "buffer_to_buffer_with_offset", "Copy from buffer to buffer using different offsets in the source and destination buffers")); |
| |
| for (deUint32 srcOffset = 0u; srcOffset < BufferOffsetParams::kMaxOffset; ++srcOffset) |
| for (deUint32 dstOffset = 0u; dstOffset < BufferOffsetParams::kMaxOffset; ++dstOffset) |
| { |
| BufferOffsetParams params{srcOffset, dstOffset}; |
| addFunctionCase(subGroup.get(), de::toString(srcOffset) + "_" + de::toString(dstOffset), "", bufferOffsetTest, params); |
| } |
| |
| group->addChild(subGroup.release()); |
| } |
| |
| void addResolveImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| addTestGroup(group, "whole", "Resolve from image to image (whole)", addResolveImageWholeTests, allocationKind, extensionUse); |
| addTestGroup(group, "partial", "Resolve from image to image (partial)", addResolveImagePartialTests, allocationKind, extensionUse); |
| addTestGroup(group, "with_regions", "Resolve from image to image (with regions)", addResolveImageWithRegionsTests, allocationKind, extensionUse); |
| addTestGroup(group, "whole_copy_before_resolving", "Resolve from image to image (whole copy before resolving)", addResolveImageWholeCopyBeforeResolvingTests, allocationKind, extensionUse); |
| addTestGroup(group, "diff_layout_copy_before_resolving", "Resolve from image to image (whole copy before resolving with different layouts)", addResolveImageWholeCopyDiffLayoutsBeforeResolvingTests, allocationKind, extensionUse); |
| addTestGroup(group, "whole_array_image", "Resolve from image to image (whole array image)", addResolveImageWholeArrayImageTests, allocationKind, extensionUse); |
| addTestGroup(group, "whole_array_image_one_region", "Resolve from image to image (whole array image with single region)", addResolveImageWholeArrayImageSingleRegionTests, allocationKind, extensionUse); |
| addTestGroup(group, "diff_image_size", "Resolve from image to image of different size", addResolveImageDiffImageSizeTests, allocationKind, extensionUse); |
| } |
| |
| void addCopiesAndBlittingTests (tcu::TestCaseGroup* group, AllocationKind allocationKind, ExtensionUse extensionUse) |
| { |
| addTestGroup(group, "image_to_image", "Copy from image to image", addImageToImageTests, allocationKind, extensionUse); |
| addTestGroup(group, "image_to_buffer", "Copy from image to buffer", addImageToBufferTests, allocationKind, extensionUse); |
| addTestGroup(group, "buffer_to_image", "Copy from buffer to image", addBufferToImageTests, allocationKind, extensionUse); |
| addTestGroup(group, "buffer_to_depthstencil", "Copy from buffer to depth/Stencil", addBufferToDepthStencilTests, allocationKind, extensionUse); |
| addTestGroup(group, "buffer_to_buffer", "Copy from buffer to buffer", addBufferToBufferTests, allocationKind, extensionUse); |
| addTestGroup(group, "blit_image", "Blitting image", addBlittingImageTests, allocationKind, extensionUse); |
| addTestGroup(group, "resolve_image", "Resolve image", addResolveImageTests, allocationKind, extensionUse); |
| } |
| |
| void addCoreCopiesAndBlittingTests(tcu::TestCaseGroup* group) |
| { |
| addCopiesAndBlittingTests(group, ALLOCATION_KIND_SUBALLOCATED, EXTENSION_USE_NONE); |
| addBufferCopyOffsetTests(group); |
| } |
| |
| |
| void addDedicatedAllocationCopiesAndBlittingTests (tcu::TestCaseGroup* group) |
| { |
| addCopiesAndBlittingTests(group, ALLOCATION_KIND_DEDICATED, EXTENSION_USE_NONE); |
| } |
| |
| void addExtensionCopiesAndBlittingTests(tcu::TestCaseGroup* group) |
| { |
| addCopiesAndBlittingTests(group, ALLOCATION_KIND_DEDICATED, EXTENSION_USE_COPY_COMMANDS2); |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createCopiesAndBlittingTests (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> copiesAndBlittingTests(new tcu::TestCaseGroup(testCtx, "copy_and_blit", "Copies And Blitting Tests")); |
| |
| copiesAndBlittingTests->addChild(createTestGroup(testCtx, "core", "Core Copies And Blitting Tests", addCoreCopiesAndBlittingTests)); |
| copiesAndBlittingTests->addChild(createTestGroup(testCtx, "dedicated_allocation", "Copies And Blitting Tests For Dedicated Memory Allocation", addDedicatedAllocationCopiesAndBlittingTests)); |
| copiesAndBlittingTests->addChild(createTestGroup(testCtx, "copy_commands2", "Copies And Blitting Tests using KHR_copy_commands2", addExtensionCopiesAndBlittingTests)); |
| |
| return copiesAndBlittingTests.release(); |
| } |
| |
| } // api |
| } // vkt |