blob: 5521c213c036dffa1098b517e6a618d5336c9e2e [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2016 The Khronos Group Inc.
* Copyright (c) 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 Image Clearing Tests
*//*--------------------------------------------------------------------*/
#include "vktApiImageClearingTests.hpp"
#include "deRandom.hpp"
#include "deMath.h"
#include "deSTLUtil.hpp"
#include "deStringUtil.hpp"
#include "deUniquePtr.hpp"
#include "deArrayUtil.hpp"
#include "deInt32.h"
#include "vkImageUtil.hpp"
#include "vkMemUtil.hpp"
#include "vktTestCase.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktTestGroupUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkRefUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkCmdUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVectorType.hpp"
#include "tcuTexture.hpp"
#include "tcuFloat.hpp"
#include "tcuTestLog.hpp"
#include "tcuVectorUtil.hpp"
#include <sstream>
#include <numeric>
namespace vkt
{
namespace api
{
using namespace vk;
using namespace tcu;
namespace
{
enum AllocationKind
{
ALLOCATION_KIND_SUBALLOCATED = 0,
ALLOCATION_KIND_DEDICATED,
ALLOCATION_KIND_LAST,
};
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");
}
}
}
VkExtent3D getMipLevelExtent (VkExtent3D baseExtent, const deUint32 mipLevel)
{
baseExtent.width = std::max(baseExtent.width >> mipLevel, 1u);
baseExtent.height = std::max(baseExtent.height >> mipLevel, 1u);
baseExtent.depth = std::max(baseExtent.depth >> mipLevel, 1u);
return baseExtent;
}
deUint32 getNumMipLevels (const VkExtent3D& baseExtent, const deUint32 maxMipLevels)
{
const deUint32 widestEdge = std::max(std::max(baseExtent.width, baseExtent.height), baseExtent.depth);
return std::min(static_cast<deUint32>(deFloatLog2(static_cast<float>(widestEdge))) + 1u, maxMipLevels);
}
deUint32 greatestCommonDivisor (const deUint32 a, const deUint32 b)
{
/* Find GCD */
deUint32 temp;
deUint32 x=a;
deUint32 y=b;
while (x%y != 0)
{
temp = y;
y = x%y;
x = temp;
}
return y;
}
deUint32 lowestCommonMultiple (const deUint32 a, const deUint32 b)
{
return (a*b)/greatestCommonDivisor(a,b);
}
std::vector<deUint32> getImageMipLevelSizes (const deUint32 pixelSize, const VkExtent3D& baseExtent, const deUint32 numMipLevels, const deUint32 perLevelAlignment = 1u)
{
std::vector<deUint32> results(numMipLevels);
for (deUint32 mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
{
const VkExtent3D extent = getMipLevelExtent(baseExtent, mipLevel);
results[mipLevel] = static_cast<deUint32>(extent.width * extent.height * extent.depth * pixelSize);
results[mipLevel] = ((results[mipLevel] + perLevelAlignment-1) / perLevelAlignment) * perLevelAlignment;
}
return results;
}
struct LayerRange
{
deUint32 baseArrayLayer;
deUint32 layerCount;
};
inline bool isInClearRange (const UVec4& clearCoords, const deUint32 x, const deUint32 y, deUint32 arrayLayer = 0, tcu::Maybe<LayerRange> imageViewLayerRange = tcu::Maybe<LayerRange>(), tcu::Maybe<LayerRange> attachmentClearLayerRange = tcu::Maybe<LayerRange>())
{
if (attachmentClearLayerRange)
{
// Only layers in range passed to clear command are cleared
const deUint32 clearBaseLayer = (imageViewLayerRange ? imageViewLayerRange->baseArrayLayer : 0) + attachmentClearLayerRange->baseArrayLayer;
const deUint32 clearLayerCount = (attachmentClearLayerRange->layerCount == VK_REMAINING_ARRAY_LAYERS) ? imageViewLayerRange->layerCount : clearBaseLayer + attachmentClearLayerRange->layerCount;
if ((arrayLayer < clearBaseLayer) || (arrayLayer >= (clearLayerCount)))
{
return false;
}
}
if (clearCoords == UVec4())
{
return true;
}
//! Check if a point lies in a cross-like area.
return !((x < clearCoords[0] && y < clearCoords[1]) ||
(x < clearCoords[0] && y >= clearCoords[3]) ||
(x >= clearCoords[2] && y < clearCoords[1]) ||
(x >= clearCoords[2] && y >= clearCoords[3]));
}
inline bool isInInitialClearRange (bool isAttachmentformat, deUint32 mipLevel, deUint32 arrayLayer, LayerRange imageViewLayerRange)
{
if (!isAttachmentformat)
{
// initial clear is done using renderpass load op - does not apply for non-renderable formats
return false;
}
if (mipLevel > 0)
{
// intial clear is done using FB bound to level 0 only
return false;
}
// Only layers in range bound to framebuffer are cleared to initial color
if ((arrayLayer < imageViewLayerRange.baseArrayLayer) || (arrayLayer >= (imageViewLayerRange.baseArrayLayer + imageViewLayerRange.layerCount)))
{
return false;
}
return true;
}
// This method is copied from the vktRenderPassTests.cpp. It should be moved to a common place.
int calcFloatDiff (float a, float b)
{
const int asign = Float32(a).sign();
const int bsign = Float32(a).sign();
const deUint32 avalue = (Float32(a).bits() & ((0x1u << 31u) - 1u));
const deUint32 bvalue = (Float32(b).bits() & ((0x1u << 31u) - 1u));
if (asign != bsign)
return avalue + bvalue + 1u;
else if (avalue < bvalue)
return bvalue - avalue;
else
return avalue - bvalue;
}
// This method is copied from the vktRenderPassTests.cpp and extended with the stringResult parameter.
bool comparePixelToDepthClearValue (const ConstPixelBufferAccess& access,
int x,
int y,
float ref,
std::string& stringResult)
{
const TextureFormat format = getEffectiveDepthStencilTextureFormat(access.getFormat(), Sampler::MODE_DEPTH);
const TextureChannelClass channelClass = getTextureChannelClass(format.type);
switch (channelClass)
{
case TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
case TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
{
const int bitDepth = getTextureFormatBitDepth(format).x();
const float depth = access.getPixDepth(x, y);
const float threshold = 2.0f / (float)((1 << bitDepth) - 1);
const bool result = deFloatAbs(depth - ref) <= threshold;
if (!result)
{
std::stringstream s;
s << "Ref:" << ref << " Threshold:" << threshold << " Depth:" << depth;
stringResult = s.str();
}
return result;
}
case TEXTURECHANNELCLASS_FLOATING_POINT:
{
const float depth = access.getPixDepth(x, y);
const int mantissaBits = getTextureFormatMantissaBitDepth(format).x();
const int threshold = 10 * 1 << (23 - mantissaBits);
DE_ASSERT(mantissaBits <= 23);
const bool result = calcFloatDiff(depth, ref) <= threshold;
if (!result)
{
float floatThreshold = Float32((deUint32)threshold).asFloat();
std::stringstream s;
s << "Ref:" << ref << " Threshold:" << floatThreshold << " Depth:" << depth;
stringResult = s.str();
}
return result;
}
default:
DE_FATAL("Invalid channel class");
return false;
}
}
// This method is copied from the vktRenderPassTests.cpp and extended with the stringResult parameter.
bool comparePixelToStencilClearValue (const ConstPixelBufferAccess& access,
int x,
int y,
deUint32 ref,
std::string& stringResult)
{
const deUint32 stencil = access.getPixStencil(x, y);
const bool result = stencil == ref;
if (!result)
{
std::stringstream s;
s << "Ref:" << ref << " Threshold:0" << " Stencil:" << stencil;
stringResult = s.str();
}
return result;
}
// This method is copied from the vktRenderPassTests.cpp and extended with the stringResult parameter.
bool comparePixelToColorClearValue (const ConstPixelBufferAccess& access,
int x,
int y,
int z,
const VkClearColorValue& ref,
std::string& stringResult)
{
const TextureFormat format = access.getFormat();
const TextureChannelClass channelClass = getTextureChannelClass(format.type);
const BVec4 channelMask = getTextureFormatChannelMask(format);
switch (channelClass)
{
case TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
case TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
{
const IVec4 bitDepth (getTextureFormatBitDepth(format));
const Vec4 resColor (access.getPixel(x, y, z));
Vec4 refColor (ref.float32[0],
ref.float32[1],
ref.float32[2],
ref.float32[3]);
const int modifier = (channelClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) ? 0 : 1;
const Vec4 threshold (bitDepth[0] > 0 ? 1.0f / ((float)(1 << (bitDepth[0] - modifier)) - 1.0f) : 1.0f,
bitDepth[1] > 0 ? 1.0f / ((float)(1 << (bitDepth[1] - modifier)) - 1.0f) : 1.0f,
bitDepth[2] > 0 ? 1.0f / ((float)(1 << (bitDepth[2] - modifier)) - 1.0f) : 1.0f,
bitDepth[3] > 0 ? 1.0f / ((float)(1 << (bitDepth[3] - modifier)) - 1.0f) : 1.0f);
if (isSRGB(access.getFormat()))
refColor = linearToSRGB(refColor);
const bool result = !(anyNotEqual(logicalAnd(lessThanEqual(absDiff(resColor, refColor), threshold), channelMask), channelMask));
if (!result)
{
std::stringstream s;
s << "Ref:" << refColor << " Mask:" << channelMask << " Threshold:" << threshold << " Color:" << resColor;
stringResult = s.str();
}
return result;
}
case TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
{
const UVec4 resColor (access.getPixelUint(x, y, z));
const UVec4 refColor (ref.uint32[0],
ref.uint32[1],
ref.uint32[2],
ref.uint32[3]);
const UVec4 threshold (1);
const bool result = !(anyNotEqual(logicalAnd(lessThanEqual(absDiff(resColor, refColor), threshold), channelMask), channelMask));
if (!result)
{
std::stringstream s;
s << "Ref:" << refColor << " Mask:" << channelMask << " Threshold:" << threshold << " Color:" << resColor;
stringResult = s.str();
}
return result;
}
case TEXTURECHANNELCLASS_SIGNED_INTEGER:
{
const IVec4 resColor (access.getPixelInt(x, y, z));
const IVec4 refColor (ref.int32[0],
ref.int32[1],
ref.int32[2],
ref.int32[3]);
const IVec4 threshold (1);
const bool result = !(anyNotEqual(logicalAnd(lessThanEqual(absDiff(resColor, refColor), threshold), channelMask), channelMask));
if (!result)
{
std::stringstream s;
s << "Ref:" << refColor << " Mask:" << channelMask << " Threshold:" << threshold << " Color:" << resColor;
stringResult = s.str();
}
return result;
}
case TEXTURECHANNELCLASS_FLOATING_POINT:
{
const Vec4 resColor (access.getPixel(x, y, z));
const Vec4 refColor (ref.float32[0],
ref.float32[1],
ref.float32[2],
ref.float32[3]);
const IVec4 mantissaBits (getTextureFormatMantissaBitDepth(format));
const IVec4 threshold (10 * IVec4(1) << (23 - mantissaBits));
DE_ASSERT(allEqual(greaterThanEqual(threshold, IVec4(0)), BVec4(true)));
for (int ndx = 0; ndx < 4; ndx++)
{
const bool result = !(calcFloatDiff(resColor[ndx], refColor[ndx]) > threshold[ndx] && channelMask[ndx]);
if (!result)
{
float floatThreshold = Float32((deUint32)(threshold)[0]).asFloat();
Vec4 thresholdVec4 (floatThreshold,
floatThreshold,
floatThreshold,
floatThreshold);
std::stringstream s;
s << "Ref:" << refColor << " Mask:" << channelMask << " Threshold:" << thresholdVec4 << " Color:" << resColor;
stringResult = s.str();
return false;
}
}
return true;
}
default:
DE_FATAL("Invalid channel class");
return false;
}
}
std::string extentToString (VkExtent3D extent, VkImageType imageType)
{
// Don't append image dimensions when using the dimensions found in original test cases. This avoids name clashing with the old versions.
if (imageType == VK_IMAGE_TYPE_1D && extent.width == 256u) return "";
if (imageType == VK_IMAGE_TYPE_2D && extent.width == 256u && extent.height == 256u) return "";
if (imageType == VK_IMAGE_TYPE_3D && extent.width == 256u && extent.height == 256u && extent.depth == 16u) return "";
return (std::string("_") + de::toString(extent.width) + std::string("x") + de::toString(extent.height) + (extent.depth != 1 ? (std::string("x") + de::toString(extent.depth)) : ""));
}
struct TestParams
{
bool useSingleMipLevel; //!< only mip level 0, otherwise up to maxMipLevels
VkImageType imageType;
VkFormat imageFormat;
VkImageTiling imageTiling;
VkExtent3D imageExtent;
deUint32 imageLayerCount;
LayerRange imageViewLayerRange;
VkClearValue initValue;
VkClearValue clearValue[2]; //!< the second value is used with more than one mip map
LayerRange clearLayerRange;
AllocationKind allocationKind;
bool isCube;
};
class ImageClearingTestInstance : public vkt::TestInstance
{
public:
ImageClearingTestInstance (Context& context,
const TestParams& testParams);
Move<VkCommandPool> createCommandPool (VkCommandPoolCreateFlags commandPoolCreateFlags) const;
Move<VkCommandBuffer> allocatePrimaryCommandBuffer (VkCommandPool commandPool) const;
Move<VkImage> createImage (VkImageType imageType, VkFormat format, VkImageTiling tiling, VkExtent3D extent, deUint32 arrayLayerCount, VkImageUsageFlags usage) const;
Move<VkImageView> createImageView (VkImage image, VkImageViewType viewType, VkFormat format, VkImageAspectFlags aspectMask, LayerRange layerRange) const;
Move<VkRenderPass> createRenderPass (VkFormat format) const;
Move<VkFramebuffer> createFrameBuffer (VkImageView imageView, VkRenderPass renderPass, deUint32 imageWidth, deUint32 imageHeight, deUint32 imageLayersCount) const;
void beginCommandBuffer (VkCommandBufferUsageFlags usageFlags) const;
void endCommandBuffer (void) const;
void submitCommandBuffer (void) const;
void beginRenderPass (VkSubpassContents content, VkClearValue clearValue) const;
void pipelineImageBarrier (VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const;
de::MovePtr<TextureLevelPyramid> readImage (VkImageAspectFlags aspectMask, deUint32 baseLayer) const;
tcu::TestStatus verifyResultImage (const std::string& successMessage, const UVec4& clearCoords = UVec4()) const;
protected:
enum ViewType
{
VIEW_TYPE_SINGLE,
VIEW_TYPE_ARRAY,
VIEW_TYPE_CUBE
};
VkImageViewType getCorrespondingImageViewType (VkImageType imageType, ViewType viewType) const;
VkImageUsageFlags getImageUsageFlags (VkFormat format) const;
VkImageAspectFlags getImageAspectFlags (VkFormat format) const;
bool getIsAttachmentFormat (VkFormat format, VkImageTiling tiling) const;
bool getIsStencilFormat (VkFormat format) const;
bool getIsDepthFormat (VkFormat format) const;
VkImageFormatProperties getImageFormatProperties (void) const;
VkImageCreateFlags getImageCreateFlags (void) const;
ViewType getViewType (deUint32 imageLayerCount) const;
de::MovePtr<Allocation> allocateAndBindImageMemory (VkImage image) const;
const TestParams& m_params;
const VkDevice m_device;
const InstanceInterface& m_vki;
const DeviceInterface& m_vkd;
const VkQueue m_queue;
const deUint32 m_queueFamilyIndex;
Allocator& m_allocator;
const bool m_isAttachmentFormat;
const VkImageUsageFlags m_imageUsageFlags;
const VkImageAspectFlags m_imageAspectFlags;
const VkImageFormatProperties m_imageFormatProperties;
const deUint32 m_imageMipLevels;
const deUint32 m_thresholdMipLevel;
Unique<VkCommandPool> m_commandPool;
Unique<VkCommandBuffer> m_commandBuffer;
Unique<VkImage> m_image;
de::MovePtr<Allocation> m_imageMemory;
Unique<VkImageView> m_imageView;
Unique<VkRenderPass> m_renderPass;
Unique<VkFramebuffer> m_frameBuffer;
};
ImageClearingTestInstance::ImageClearingTestInstance (Context& context, const TestParams& params)
: TestInstance (context)
, m_params (params)
, m_device (context.getDevice())
, m_vki (context.getInstanceInterface())
, m_vkd (context.getDeviceInterface())
, m_queue (context.getUniversalQueue())
, m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
, m_allocator (context.getDefaultAllocator())
, m_isAttachmentFormat (getIsAttachmentFormat(params.imageFormat, params.imageTiling))
, m_imageUsageFlags (getImageUsageFlags(params.imageFormat))
, m_imageAspectFlags (getImageAspectFlags(params.imageFormat))
, m_imageFormatProperties (getImageFormatProperties())
, m_imageMipLevels (params.useSingleMipLevel ? 1u : getNumMipLevels(params.imageExtent, m_imageFormatProperties.maxMipLevels))
, m_thresholdMipLevel (std::max(m_imageMipLevels / 2u, 1u))
, m_commandPool (createCommandPool(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT))
, m_commandBuffer (allocatePrimaryCommandBuffer(*m_commandPool))
, m_image (createImage(params.imageType,
params.imageFormat,
params.imageTiling,
params.imageExtent,
params.imageLayerCount,
m_imageUsageFlags))
, m_imageMemory (allocateAndBindImageMemory(*m_image))
, m_imageView (m_isAttachmentFormat ? createImageView(*m_image,
getCorrespondingImageViewType(params.imageType, getViewType(params.imageLayerCount)),
params.imageFormat,
m_imageAspectFlags,
params.imageViewLayerRange) : vk::Move<VkImageView>())
, m_renderPass (m_isAttachmentFormat ? createRenderPass(params.imageFormat) : vk::Move<vk::VkRenderPass>())
, m_frameBuffer (m_isAttachmentFormat ? createFrameBuffer(*m_imageView, *m_renderPass, params.imageExtent.width, params.imageExtent.height, params.imageViewLayerRange.layerCount) : vk::Move<vk::VkFramebuffer>())
{
if (m_params.allocationKind == ALLOCATION_KIND_DEDICATED)
context.requireDeviceExtension("VK_KHR_dedicated_allocation");
}
ImageClearingTestInstance::ViewType ImageClearingTestInstance::getViewType (deUint32 imageLayerCount) const
{
if (imageLayerCount > 1u)
return m_params.isCube ? VIEW_TYPE_CUBE : VIEW_TYPE_ARRAY;
else
return VIEW_TYPE_SINGLE;
}
VkImageViewType ImageClearingTestInstance::getCorrespondingImageViewType (VkImageType imageType, ViewType viewType) const
{
switch (imageType)
{
case VK_IMAGE_TYPE_1D:
return (viewType == VIEW_TYPE_ARRAY) ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D;
case VK_IMAGE_TYPE_2D:
if (viewType == VIEW_TYPE_ARRAY)
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
else if (viewType == VIEW_TYPE_CUBE)
return VK_IMAGE_VIEW_TYPE_CUBE;
else
return VK_IMAGE_VIEW_TYPE_2D;
case VK_IMAGE_TYPE_3D:
if (viewType != VIEW_TYPE_SINGLE)
{
DE_FATAL("Cannot have 3D image array");
}
return VK_IMAGE_VIEW_TYPE_3D;
default:
DE_FATAL("Unknown image type!");
}
return VK_IMAGE_VIEW_TYPE_2D;
}
VkImageUsageFlags ImageClearingTestInstance::getImageUsageFlags (VkFormat format) const
{
VkImageUsageFlags commonFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (m_isAttachmentFormat)
{
if (isDepthStencilFormat(format))
return commonFlags | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
return commonFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
return commonFlags;
}
VkImageAspectFlags ImageClearingTestInstance::getImageAspectFlags (VkFormat format) const
{
VkImageAspectFlags imageAspectFlags = 0;
if (getIsDepthFormat(format))
imageAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (getIsStencilFormat(format))
imageAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
if (imageAspectFlags == 0)
imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
return imageAspectFlags;
}
bool ImageClearingTestInstance::getIsAttachmentFormat (VkFormat format, VkImageTiling tiling) const
{
const VkFormatProperties props = vk::getPhysicalDeviceFormatProperties(m_vki, m_context.getPhysicalDevice(), format);
const VkFormatFeatureFlags features = tiling == VK_IMAGE_TILING_OPTIMAL ? props.optimalTilingFeatures : props.linearTilingFeatures;
return (features & (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) != 0;
}
bool ImageClearingTestInstance::getIsStencilFormat (VkFormat format) const
{
const TextureFormat tcuFormat = mapVkFormat(format);
if (tcuFormat.order == TextureFormat::S || tcuFormat.order == TextureFormat::DS)
return true;
return false;
}
bool ImageClearingTestInstance::getIsDepthFormat (VkFormat format) const
{
const TextureFormat tcuFormat = mapVkFormat(format);
if (tcuFormat.order == TextureFormat::D || tcuFormat.order == TextureFormat::DS)
return true;
return false;
}
VkImageCreateFlags ImageClearingTestInstance::getImageCreateFlags (void) const
{
return m_params.isCube ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlags)0;
}
VkImageFormatProperties ImageClearingTestInstance::getImageFormatProperties (void) const
{
VkImageFormatProperties properties;
const VkResult result = m_vki.getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(), m_params.imageFormat, m_params.imageType,
m_params.imageTiling, m_imageUsageFlags, getImageCreateFlags(), &properties);
if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
TCU_THROW(NotSupportedError, "Format not supported");
else
return properties;
}
de::MovePtr<Allocation> ImageClearingTestInstance::allocateAndBindImageMemory (VkImage image) const
{
de::MovePtr<Allocation> imageMemory (allocateImage(m_vki, m_vkd, m_context.getPhysicalDevice(), m_device, image, MemoryRequirement::Any, m_allocator, m_params.allocationKind));
VK_CHECK(m_vkd.bindImageMemory(m_device, image, imageMemory->getMemory(), imageMemory->getOffset()));
return imageMemory;
}
Move<VkCommandPool> ImageClearingTestInstance::createCommandPool (VkCommandPoolCreateFlags commandPoolCreateFlags) const
{
return vk::createCommandPool(m_vkd, m_device, commandPoolCreateFlags, m_queueFamilyIndex);
}
Move<VkCommandBuffer> ImageClearingTestInstance::allocatePrimaryCommandBuffer (VkCommandPool commandPool) const
{
return vk::allocateCommandBuffer(m_vkd, m_device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
}
Move<VkImage> ImageClearingTestInstance::createImage (VkImageType imageType, VkFormat format, VkImageTiling tiling, VkExtent3D extent, deUint32 arrayLayerCount, VkImageUsageFlags usage) const
{
if (arrayLayerCount > m_imageFormatProperties.maxArrayLayers)
TCU_THROW(NotSupportedError, "Device does not support enough image array layers");
const VkImageCreateInfo imageCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
getImageCreateFlags(), // VkImageCreateFlags flags;
imageType, // VkImageType imageType;
format, // VkFormat format;
extent, // VkExtent3D extent;
m_imageMipLevels, // deUint32 mipLevels;
arrayLayerCount, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
tiling, // VkImageTiling tiling;
usage, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&m_queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
return vk::createImage(m_vkd, m_device, &imageCreateInfo, DE_NULL);
}
Move<VkImageView> ImageClearingTestInstance::createImageView (VkImage image, VkImageViewType viewType, VkFormat format, VkImageAspectFlags aspectMask, LayerRange layerRange) const
{
const VkImageViewCreateInfo imageViewCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
image, // VkImage image;
viewType, // VkImageViewType viewType;
format, // VkFormat format;
{
VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle r;
VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle g;
VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle b;
VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle a;
}, // VkComponentMapping components;
{
aspectMask, // VkImageAspectFlags aspectMask;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
layerRange.baseArrayLayer, // deUint32 baseArrayLayer;
layerRange.layerCount, // deUint32 arraySize;
}, // VkImageSubresourceRange subresourceRange;
};
return vk::createImageView(m_vkd, m_device, &imageViewCreateInfo, DE_NULL);
}
Move<VkRenderPass> ImageClearingTestInstance::createRenderPass (VkFormat format) const
{
VkImageLayout imageLayout;
if (isDepthStencilFormat(format))
imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
else
imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
const VkAttachmentDescription attachmentDesc =
{
0u, // VkAttachmentDescriptionFlags flags;
format, // VkFormat format;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
imageLayout, // VkImageLayout initialLayout;
imageLayout, // VkImageLayout finalLayout;
};
const VkAttachmentDescription attachments[1] =
{
attachmentDesc
};
const VkAttachmentReference attachmentRef =
{
0u, // deUint32 attachment;
imageLayout, // VkImageLayout layout;
};
const VkAttachmentReference* pColorAttachments = DE_NULL;
const VkAttachmentReference* pDepthStencilAttachment = DE_NULL;
deUint32 colorAttachmentCount = 1;
if (isDepthStencilFormat(format))
{
colorAttachmentCount = 0;
pDepthStencilAttachment = &attachmentRef;
}
else
{
colorAttachmentCount = 1;
pColorAttachments = &attachmentRef;
}
const VkSubpassDescription subpassDesc[1] =
{
{
0u, // VkSubpassDescriptionFlags flags;
VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
0u, // deUint32 inputAttachmentCount;
DE_NULL, // const VkAttachmentReference* pInputAttachments;
colorAttachmentCount, // deUint32 colorAttachmentCount;
pColorAttachments, // const VkAttachmentReference* pColorAttachments;
DE_NULL, // const VkAttachmentReference* pResolveAttachments;
pDepthStencilAttachment, // const VkAttachmentReference* pDepthStencilAttachment;
0u, // deUint32 preserveAttachmentCount;
DE_NULL, // const VkAttachmentReference* pPreserveAttachments;
}
};
const VkRenderPassCreateInfo renderPassCreateInfo =
{
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkRenderPassCreateFlags flags;
1u, // deUint32 attachmentCount;
attachments, // const VkAttachmentDescription* pAttachments;
1u, // deUint32 subpassCount;
subpassDesc, // const VkSubpassDescription* pSubpasses;
0u, // deUint32 dependencyCount;
DE_NULL, // const VkSubpassDependency* pDependencies;
};
return vk::createRenderPass(m_vkd, m_device, &renderPassCreateInfo, DE_NULL);
}
Move<VkFramebuffer> ImageClearingTestInstance::createFrameBuffer (VkImageView imageView, VkRenderPass renderPass, deUint32 imageWidth, deUint32 imageHeight, deUint32 imageLayersCount) const
{
const VkImageView attachmentViews[1] =
{
imageView
};
const VkFramebufferCreateInfo framebufferCreateInfo =
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkFramebufferCreateFlags flags;
renderPass, // VkRenderPass renderPass;
1, // deUint32 attachmentCount;
attachmentViews, // const VkImageView* pAttachments;
imageWidth, // deUint32 width;
imageHeight, // deUint32 height;
imageLayersCount, // deUint32 layers;
};
return createFramebuffer(m_vkd, m_device, &framebufferCreateInfo, DE_NULL);
}
void ImageClearingTestInstance::beginCommandBuffer (VkCommandBufferUsageFlags usageFlags) const
{
vk::beginCommandBuffer(m_vkd, *m_commandBuffer, usageFlags);
}
void ImageClearingTestInstance::endCommandBuffer (void) const
{
vk::endCommandBuffer(m_vkd, *m_commandBuffer);
}
void ImageClearingTestInstance::submitCommandBuffer (void) const
{
submitCommandsAndWait(m_vkd, m_device, m_queue, m_commandBuffer.get());
}
void ImageClearingTestInstance::pipelineImageBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
{
const VkImageMemoryBarrier imageBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
srcAccessMask, // VkAccessFlags srcAccessMask;
dstAccessMask, // VkAccessFlags dstAccessMask;
oldLayout, // VkImageLayout oldLayout;
newLayout, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
*m_image, // VkImage image;
{
m_imageAspectFlags, // VkImageAspectFlags aspectMask;
0u, // deUint32 baseMipLevel;
VK_REMAINING_MIP_LEVELS, // deUint32 levelCount;
0u, // deUint32 baseArrayLayer;
VK_REMAINING_ARRAY_LAYERS, // deUint32 layerCount;
}, // VkImageSubresourceRange subresourceRange;
};
m_vkd.cmdPipelineBarrier(*m_commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
}
de::MovePtr<TextureLevelPyramid> ImageClearingTestInstance::readImage (VkImageAspectFlags aspectMask, deUint32 arrayLayer) const
{
const TextureFormat tcuFormat = aspectMask == VK_IMAGE_ASPECT_COLOR_BIT ? mapVkFormat(m_params.imageFormat) :
aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT ? getDepthCopyFormat(m_params.imageFormat) :
aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT ? getStencilCopyFormat(m_params.imageFormat) :
TextureFormat();
const deUint32 pixelSize = getPixelSize(tcuFormat);
deUint32 alignment = 4; // subsequent mip levels aligned to 4 bytes
if (!getIsDepthFormat(m_params.imageFormat) && !getIsStencilFormat(m_params.imageFormat))
alignment = lowestCommonMultiple(pixelSize, alignment); // alignment must be multiple of pixel size, if not D/S.
const std::vector<deUint32> mipLevelSizes = getImageMipLevelSizes(pixelSize, m_params.imageExtent, m_imageMipLevels, alignment);
const VkDeviceSize imageTotalSize = std::accumulate(mipLevelSizes.begin(), mipLevelSizes.end(), 0u);
de::MovePtr<TextureLevelPyramid> result (new TextureLevelPyramid(tcuFormat, m_imageMipLevels));
Move<VkBuffer> buffer;
de::MovePtr<Allocation> bufferAlloc;
// Create destination buffer
{
const VkBufferCreateInfo bufferParams =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags;
imageTotalSize, // VkDeviceSize size;
VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
0u, // deUint32 queueFamilyIndexCount;
DE_NULL // const deUint32* pQueueFamilyIndices;
};
buffer = createBuffer(m_vkd, m_device, &bufferParams);
bufferAlloc = allocateBuffer(m_vki, m_vkd, m_context.getPhysicalDevice(), m_device, *buffer, MemoryRequirement::HostVisible, m_allocator, m_params.allocationKind);
VK_CHECK(m_vkd.bindBufferMemory(m_device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
}
// Barriers for copying image to buffer
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;
imageTotalSize, // VkDeviceSize size;
};
// Copy image to buffer
std::vector<VkBufferImageCopy> copyRegions;
{
deUint32 offset = 0u;
for (deUint32 mipLevel = 0; mipLevel < m_imageMipLevels; ++mipLevel)
{
const VkExtent3D extent = getMipLevelExtent(m_params.imageExtent, mipLevel);
const VkBufferImageCopy region =
{
offset, // VkDeviceSize bufferOffset;
0u, // deUint32 bufferRowLength;
0u, // deUint32 bufferImageHeight;
{ aspectMask, mipLevel, arrayLayer, 1u }, // VkImageSubresourceLayers imageSubresource;
{ 0, 0, 0 }, // VkOffset3D imageOffset;
extent // VkExtent3D imageExtent;
};
copyRegions.push_back(region);
offset += mipLevelSizes[mipLevel];
}
}
beginCommandBuffer(0);
pipelineImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_vkd.cmdCopyImageToBuffer(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, static_cast<deUint32>(copyRegions.size()), &copyRegions[0]);
m_vkd.cmdPipelineBarrier(*m_commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
pipelineImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_IMAGE_LAYOUT_GENERAL);
endCommandBuffer();
submitCommandBuffer();
invalidateAlloc(m_vkd, m_device, *bufferAlloc);
{
deUint32 offset = 0u;
for (deUint32 mipLevel = 0; mipLevel < m_imageMipLevels; ++mipLevel)
{
const VkExtent3D extent = getMipLevelExtent(m_params.imageExtent, mipLevel);
const void* pLevelData = static_cast<const void*>(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()) + offset);
result->allocLevel(mipLevel, extent.width, extent.height, extent.depth);
copy(result->getLevel(mipLevel), ConstPixelBufferAccess(result->getFormat(), result->getLevel(mipLevel).getSize(), pLevelData));
offset += mipLevelSizes[mipLevel];
}
}
return result;
}
tcu::TestStatus ImageClearingTestInstance::verifyResultImage (const std::string& successMessage, const UVec4& clearCoords) const
{
DE_ASSERT((clearCoords == UVec4()) || m_params.imageExtent.depth == 1u);
if (getIsDepthFormat(m_params.imageFormat))
{
DE_ASSERT(m_imageMipLevels == 1u);
for (deUint32 arrayLayer = 0; arrayLayer < m_params.imageLayerCount; ++arrayLayer)
{
de::MovePtr<TextureLevelPyramid> image = readImage(VK_IMAGE_ASPECT_DEPTH_BIT, arrayLayer);
std::string message;
float depthValue;
for (deUint32 y = 0; y < m_params.imageExtent.height; ++y)
for (deUint32 x = 0; x < m_params.imageExtent.width; ++x)
{
if (isInClearRange(clearCoords, x, y, arrayLayer, m_params.imageViewLayerRange, m_params.clearLayerRange))
depthValue = m_params.clearValue[0].depthStencil.depth;
else
if (isInInitialClearRange(m_isAttachmentFormat, 0u /* mipLevel */, arrayLayer, m_params.imageViewLayerRange))
{
depthValue = m_params.initValue.depthStencil.depth;
}
else
continue;
if (!comparePixelToDepthClearValue(image->getLevel(0), x, y, depthValue, message))
return TestStatus::fail("Depth value mismatch! " + message);
}
}
}
if (getIsStencilFormat(m_params.imageFormat))
{
DE_ASSERT(m_imageMipLevels == 1u);
for (deUint32 arrayLayer = 0; arrayLayer < m_params.imageLayerCount; ++arrayLayer)
{
de::MovePtr<TextureLevelPyramid> image = readImage(VK_IMAGE_ASPECT_STENCIL_BIT, arrayLayer);
std::string message;
deUint32 stencilValue;
for (deUint32 y = 0; y < m_params.imageExtent.height; ++y)
for (deUint32 x = 0; x < m_params.imageExtent.width; ++x)
{
if (isInClearRange(clearCoords, x, y, arrayLayer, m_params.imageViewLayerRange, m_params.clearLayerRange))
stencilValue = m_params.clearValue[0].depthStencil.stencil;
else
if (isInInitialClearRange(m_isAttachmentFormat, 0u /* mipLevel */, arrayLayer, m_params.imageViewLayerRange))
{
stencilValue = m_params.initValue.depthStencil.stencil;
}
else
continue;
if (!comparePixelToStencilClearValue(image->getLevel(0), x, y, stencilValue, message))
return TestStatus::fail("Stencil value mismatch! " + message);
}
}
}
if (!isDepthStencilFormat(m_params.imageFormat))
{
for (deUint32 arrayLayer = 0; arrayLayer < m_params.imageLayerCount; ++arrayLayer)
{
de::MovePtr<TextureLevelPyramid> image = readImage(VK_IMAGE_ASPECT_COLOR_BIT, arrayLayer);
std::string message;
const VkClearColorValue* pColorValue;
for (deUint32 mipLevel = 0; mipLevel < m_imageMipLevels; ++mipLevel)
{
const int clearColorNdx = (mipLevel < m_thresholdMipLevel ? 0 : 1);
const VkExtent3D extent = getMipLevelExtent(m_params.imageExtent, mipLevel);
for (deUint32 z = 0; z < extent.depth; ++z)
for (deUint32 y = 0; y < extent.height; ++y)
for (deUint32 x = 0; x < extent.width; ++x)
{
if (isInClearRange(clearCoords, x, y, arrayLayer, m_params.imageViewLayerRange, m_params.clearLayerRange))
pColorValue = &m_params.clearValue[clearColorNdx].color;
else
{
if (isInInitialClearRange(m_isAttachmentFormat, mipLevel, arrayLayer, m_params.imageViewLayerRange))
{
pColorValue = &m_params.initValue.color;
}
else
continue;
}
if (!comparePixelToColorClearValue(image->getLevel(mipLevel), x, y, z, *pColorValue, message))
return TestStatus::fail("Color value mismatch! " + message);
}
}
}
}
return TestStatus::pass(successMessage);
}
void ImageClearingTestInstance::beginRenderPass (VkSubpassContents content, VkClearValue clearValue) const
{
vk::beginRenderPass(m_vkd, *m_commandBuffer, *m_renderPass, *m_frameBuffer, makeRect2D(0, 0, m_params.imageExtent.width, m_params.imageExtent.height), clearValue, content);
}
class ClearColorImageTestInstance : public ImageClearingTestInstance
{
public:
ClearColorImageTestInstance (Context& context, const TestParams& testParams, bool twoStep = false) : ImageClearingTestInstance (context, testParams), m_twoStep(twoStep) {}
TestStatus iterate (void);
protected:
bool m_twoStep;
};
class TwoStepClearColorImageTestInstance : public ClearColorImageTestInstance
{
public:
TwoStepClearColorImageTestInstance (Context& context, const TestParams& testParams) : ClearColorImageTestInstance(context, testParams, true) {}
};
TestStatus ClearColorImageTestInstance::iterate (void)
{
std::vector<VkImageSubresourceRange> subresourceRanges;
std::vector<VkImageSubresourceRange> steptwoRanges;
if (m_imageMipLevels == 1)
{
subresourceRanges.push_back(makeImageSubresourceRange(m_imageAspectFlags, 0u, 1u, m_params.clearLayerRange.baseArrayLayer, m_twoStep ? 1 : m_params.clearLayerRange.layerCount));
steptwoRanges.push_back( makeImageSubresourceRange(m_imageAspectFlags, 0u, VK_REMAINING_MIP_LEVELS, m_params.clearLayerRange.baseArrayLayer, VK_REMAINING_ARRAY_LAYERS));
}
else
{
subresourceRanges.push_back(makeImageSubresourceRange(m_imageAspectFlags, 0u, m_thresholdMipLevel, m_params.clearLayerRange.baseArrayLayer, m_params.clearLayerRange.layerCount));
subresourceRanges.push_back(makeImageSubresourceRange(m_imageAspectFlags, m_thresholdMipLevel, VK_REMAINING_MIP_LEVELS, m_params.clearLayerRange.baseArrayLayer, m_params.clearLayerRange.layerCount));
steptwoRanges.push_back( makeImageSubresourceRange(m_imageAspectFlags, 0u, m_thresholdMipLevel, m_params.clearLayerRange.baseArrayLayer, VK_REMAINING_ARRAY_LAYERS));
steptwoRanges.push_back( makeImageSubresourceRange(m_imageAspectFlags, m_thresholdMipLevel, VK_REMAINING_MIP_LEVELS, m_params.clearLayerRange.baseArrayLayer, VK_REMAINING_ARRAY_LAYERS));
}
beginCommandBuffer(0);
pipelineImageBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask
0, // VkAccessFlags srcAccessMask
(m_isAttachmentFormat
? VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
: VK_ACCESS_TRANSFER_WRITE_BIT), // VkAccessFlags dstAccessMask
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
(m_isAttachmentFormat
? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)); // VkImageLayout newLayout;
if (m_isAttachmentFormat)
{
beginRenderPass(VK_SUBPASS_CONTENTS_INLINE, m_params.initValue);
endRenderPass(m_vkd, *m_commandBuffer);
pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, // VkPipelineStageFlags srcStageMask
VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // VkImageLayout newLayout;
}
// Different clear color per range
for (std::size_t i = 0u; i < subresourceRanges.size(); ++i)
{
m_vkd.cmdClearColorImage(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.clearValue[i].color, 1, &subresourceRanges[i]);
if (m_twoStep)
m_vkd.cmdClearColorImage(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.clearValue[i].color, 1, &steptwoRanges[i]);
}
pipelineImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags srcStageMask
VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask
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_GENERAL); // VkImageLayout newLayout;
endCommandBuffer();
submitCommandBuffer();
return verifyResultImage("cmdClearColorImage passed");
}
class ClearDepthStencilImageTestInstance : public ImageClearingTestInstance
{
public:
ClearDepthStencilImageTestInstance (Context& context, const TestParams& testParams, bool twoStep = false) : ImageClearingTestInstance (context, testParams), m_twoStep(twoStep) {}
TestStatus iterate (void);
protected:
bool m_twoStep;
};
class TwoStepClearDepthStencilImageTestInstance : public ClearDepthStencilImageTestInstance
{
public:
TwoStepClearDepthStencilImageTestInstance (Context& context, const TestParams& testParams) : ClearDepthStencilImageTestInstance (context, testParams, true) { }
};
TestStatus ClearDepthStencilImageTestInstance::iterate (void)
{
const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(m_imageAspectFlags, 0u, 1u, m_params.clearLayerRange.baseArrayLayer, m_twoStep ? 1 : m_params.clearLayerRange.layerCount);
const VkImageSubresourceRange steptwoRange = makeImageSubresourceRange(m_imageAspectFlags, 0u, VK_REMAINING_MIP_LEVELS, m_params.clearLayerRange.baseArrayLayer, VK_REMAINING_ARRAY_LAYERS);
beginCommandBuffer(0);
pipelineImageBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask
0, // VkAccessFlags srcAccessMask
(m_isAttachmentFormat
? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
: VK_ACCESS_TRANSFER_WRITE_BIT), // VkAccessFlags dstAccessMask
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
(m_isAttachmentFormat
? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)); // VkImageLayout newLayout;
if (m_isAttachmentFormat)
{
beginRenderPass(VK_SUBPASS_CONTENTS_INLINE, m_params.initValue);
endRenderPass(m_vkd, *m_commandBuffer);
pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, // VkPipelineStageFlags srcStageMask
VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // VkImageLayout newLayout;
}
m_vkd.cmdClearDepthStencilImage(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.clearValue[0].depthStencil, 1, &subresourceRange);
if (m_twoStep)
m_vkd.cmdClearDepthStencilImage(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.clearValue[0].depthStencil, 1, &steptwoRange);
pipelineImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags srcStageMask
VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask
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_GENERAL); // VkImageLayout newLayout;
endCommandBuffer();
submitCommandBuffer();
return verifyResultImage("cmdClearDepthStencilImage passed");
}
class ClearAttachmentTestInstance : public ImageClearingTestInstance
{
public:
enum ClearType
{
FULL_CLEAR,
PARTIAL_CLEAR,
};
ClearAttachmentTestInstance (Context& context, const TestParams& testParams, const ClearType clearType = FULL_CLEAR)
: ImageClearingTestInstance (context, testParams)
, m_clearType (clearType)
{
if (!m_isAttachmentFormat)
TCU_THROW(NotSupportedError, "Format not renderable");
}
TestStatus iterate (void)
{
const VkClearAttachment clearAttachment =
{
m_imageAspectFlags, // VkImageAspectFlags aspectMask;
0u, // deUint32 colorAttachment;
m_params.clearValue[0] // VkClearValue clearValue;
};
UVec4 clearCoords;
std::vector<VkClearRect> clearRects;
if (m_clearType == FULL_CLEAR)
{
const VkClearRect rect =
{
{
{ 0, 0 }, // VkOffset2D offset;
{ m_params.imageExtent.width, m_params.imageExtent.height } // VkExtent2D extent;
}, // VkRect2D rect;
m_params.clearLayerRange.baseArrayLayer, // deUint32 baseArrayLayer;
m_params.clearLayerRange.layerCount, // deUint32 layerCount;
};
clearRects.push_back(rect);
}
else
{
const deUint32 clearX = m_params.imageExtent.width / 8u;
const deUint32 clearY = m_params.imageExtent.height / 8u;
const deUint32 clearWidth = m_params.imageExtent.width / 2u;
const deUint32 clearHeight = m_params.imageExtent.height / 2u;
clearCoords = UVec4(clearX, clearY,
clearX + clearWidth, clearY + clearHeight);
const VkClearRect rects[2] =
{
{
{
{ 0, static_cast<deInt32>(clearY) }, // VkOffset2D offset;
{ m_params.imageExtent.width, clearHeight } // VkExtent2D extent;
}, // VkRect2D rect;
m_params.clearLayerRange.baseArrayLayer, // deUint32 baseArrayLayer;
m_params.clearLayerRange.layerCount // deUint32 layerCount;
},
{
{
{ static_cast<deInt32>(clearX), 0 }, // VkOffset2D offset;
{ clearWidth, m_params.imageExtent.height } // VkExtent2D extent;
}, // VkRect2D rect;
m_params.clearLayerRange.baseArrayLayer, // deUint32 baseArrayLayer;
m_params.clearLayerRange.layerCount // deUint32 layerCount;
}
};
clearRects.push_back(rects[0]);
clearRects.push_back(rects[1]);
}
const bool isDepthStencil = isDepthStencilFormat(m_params.imageFormat);
const VkAccessFlags accessMask = (isDepthStencil ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
const VkImageLayout attachmentLayout = (isDepthStencil ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
beginCommandBuffer(0);
pipelineImageBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask
0, // VkAccessFlags srcAccessMask
accessMask, // VkAccessFlags dstAccessMask
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
attachmentLayout); // VkImageLayout newLayout;
beginRenderPass(VK_SUBPASS_CONTENTS_INLINE, m_params.initValue);
m_vkd.cmdClearAttachments(*m_commandBuffer, 1, &clearAttachment, static_cast<deUint32>(clearRects.size()), &clearRects[0]);
endRenderPass(m_vkd, *m_commandBuffer);
pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, // VkPipelineStageFlags srcStageMask
VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask
accessMask, // VkAccessFlags srcAccessMask
VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask
attachmentLayout, // VkImageLayout oldLayout;
VK_IMAGE_LAYOUT_GENERAL); // VkImageLayout newLayout;
endCommandBuffer();
submitCommandBuffer();
return verifyResultImage("cmdClearAttachments passed", clearCoords);
}
private:
const ClearType m_clearType;
};
class PartialClearAttachmentTestInstance : public ClearAttachmentTestInstance
{
public:
PartialClearAttachmentTestInstance (Context& context, const TestParams& testParams) : ClearAttachmentTestInstance (context, testParams, PARTIAL_CLEAR) {}
};
VkClearValue makeClearColorValue (VkFormat format, float r, float g, float b, float a)
{
const TextureFormat tcuFormat = mapVkFormat(format);
VkClearValue clearValue;
if (getTextureChannelClass(tcuFormat.type) == TEXTURECHANNELCLASS_FLOATING_POINT
|| getTextureChannelClass(tcuFormat.type) == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
|| getTextureChannelClass(tcuFormat.type) == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
{
clearValue.color.float32[0] = r;
clearValue.color.float32[1] = g;
clearValue.color.float32[2] = b;
clearValue.color.float32[3] = a;
}
else if (getTextureChannelClass(tcuFormat.type) == TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
{
UVec4 maxValues = getFormatMaxUintValue(tcuFormat);
clearValue.color.uint32[0] = (deUint32)((float)maxValues[0] * r);
clearValue.color.uint32[1] = (deUint32)((float)maxValues[1] * g);
clearValue.color.uint32[2] = (deUint32)((float)maxValues[2] * b);
clearValue.color.uint32[3] = (deUint32)((float)maxValues[3] * a);
}
else if (getTextureChannelClass(tcuFormat.type) == TEXTURECHANNELCLASS_SIGNED_INTEGER)
{
IVec4 maxValues = getFormatMaxIntValue(tcuFormat);
clearValue.color.int32[0] = (deUint32)((float)maxValues[0] * r);
clearValue.color.int32[1] = (deUint32)((float)maxValues[1] * g);
clearValue.color.int32[2] = (deUint32)((float)maxValues[2] * b);
clearValue.color.int32[3] = (deUint32)((float)maxValues[3] * a);
}
else
DE_FATAL("Unknown channel class");
return clearValue;
}
std::string getFormatCaseName (VkFormat format)
{
return de::toLower(de::toString(getFormatStr(format)).substr(10));
}
const char* getImageTypeCaseName (VkImageType type)
{
const char* s_names[] =
{
"1d",
"2d",
"3d"
};
return s_names[type];
}
const char* getImageTilingCaseName (VkImageTiling tiling)
{
const char* s_names[] =
{
"optimal",
"linear",
};
return s_names[tiling];
}
TestCaseGroup* createImageClearingTestsCommon (TestContext& testCtx, tcu::TestCaseGroup* imageClearingTests, AllocationKind allocationKind)
{
de::MovePtr<TestCaseGroup> colorImageClearTests (new TestCaseGroup(testCtx, "clear_color_image", "Color Image Clear Tests"));
de::MovePtr<TestCaseGroup> depthStencilImageClearTests (new TestCaseGroup(testCtx, "clear_depth_stencil_image", "Color Depth/Stencil Image Tests"));
de::MovePtr<TestCaseGroup> colorAttachmentClearTests (new TestCaseGroup(testCtx, "clear_color_attachment", "Color Color Attachment Tests"));
de::MovePtr<TestCaseGroup> depthStencilAttachmentClearTests (new TestCaseGroup(testCtx, "clear_depth_stencil_attachment", "Color Depth/Stencil Attachment Tests"));
de::MovePtr<TestCaseGroup> partialColorAttachmentClearTests (new TestCaseGroup(testCtx, "partial_clear_color_attachment", "Clear Partial Color Attachment Tests"));
de::MovePtr<TestCaseGroup> partialDepthStencilAttachmentClearTests (new TestCaseGroup(testCtx, "partial_clear_depth_stencil_attachment", "Clear Partial Depth/Stencil Attachment Tests"));
// Some formats are commented out due to the tcu::TextureFormat does not support them yet.
const VkFormat colorImageFormatsToTest[] =
{
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_R8_UINT,
VK_FORMAT_R8_SINT,
VK_FORMAT_R8_SRGB,
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_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_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_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_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_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_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_R32_UINT,
VK_FORMAT_R32_SINT,
VK_FORMAT_R32_SFLOAT,
VK_FORMAT_R32G32_UINT,
VK_FORMAT_R32G32_SINT,
VK_FORMAT_R32G32_SFLOAT,
VK_FORMAT_R32G32B32_UINT,
VK_FORMAT_R32G32B32_SINT,
VK_FORMAT_R32G32B32_SFLOAT,
VK_FORMAT_R32G32B32A32_UINT,
VK_FORMAT_R32G32B32A32_SINT,
VK_FORMAT_R32G32B32A32_SFLOAT,
// VK_FORMAT_R64_UINT,
// VK_FORMAT_R64_SINT,
// VK_FORMAT_R64_SFLOAT,
// VK_FORMAT_R64G64_UINT,
// VK_FORMAT_R64G64_SINT,
// VK_FORMAT_R64G64_SFLOAT,
// VK_FORMAT_R64G64B64_UINT,
// VK_FORMAT_R64G64B64_SINT,
// VK_FORMAT_R64G64B64_SFLOAT,
// VK_FORMAT_R64G64B64A64_UINT,
// VK_FORMAT_R64G64B64A64_SINT,
// VK_FORMAT_R64G64B64A64_SFLOAT,
VK_FORMAT_B10G11R11_UFLOAT_PACK32,
VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
// 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_BC2_UNORM_BLOCK,
// VK_FORMAT_BC2_SRGB_BLOCK,
// VK_FORMAT_BC3_UNORM_BLOCK,
// VK_FORMAT_BC3_SRGB_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_BC7_SRGB_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_ETC2_R8G8B8A8_UNORM_BLOCK,
// VK_FORMAT_ETC2_R8G8B8A8_SRGB_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_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
};
const size_t numOfColorImageFormatsToTest = DE_LENGTH_OF_ARRAY(colorImageFormatsToTest);
const VkFormat depthStencilImageFormatsToTest[] =
{
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 size_t numOfDepthStencilImageFormatsToTest = DE_LENGTH_OF_ARRAY(depthStencilImageFormatsToTest);
struct ImageLayerParams
{
deUint32 imageLayerCount;
LayerRange imageViewRange;
LayerRange clearLayerRange;
bool twoStep;
const char* testName;
bool isCube;
};
const ImageLayerParams imageLayerParamsToTest[] =
{
{
1u, // imageLayerCount
{0u, 1u}, // imageViewRange
{0u, 1u}, // clearLayerRange
false, // twoStep
"single_layer", // testName
false // isCube
},
{
16u, // imageLayerCount
{3u, 12u}, // imageViewRange
{2u, 5u}, // clearLayerRange
false, // twoStep
"multiple_layers", // testName
false // isCube
},
{
15u, // imageLayerCount
{ 3u, 6u }, // imageViewRange
{ 2u, 1u }, // clearLayerRange
false, // twoStep
"cube_layers", // testName
true // isCube
},
{
16u, // imageLayerCount
{ 3u, 12u }, // imageViewRange
{ 8u, VK_REMAINING_ARRAY_LAYERS }, // clearLayerRange
false, // twoStep
"remaining_array_layers", // testName
false // isCube
},
{
16u, // imageLayerCount
{ 3u, 12u }, // imageViewRange
{ 8u, VK_REMAINING_ARRAY_LAYERS }, // clearLayerRange
true, // twoStep
"remaining_array_layers_twostep", // testName
false // isCube
}
};
// Include test cases with VK_REMAINING_ARRAY_LAYERS when using vkCmdClearColorImage
const size_t numOfImageLayerParamsToTest = DE_LENGTH_OF_ARRAY(imageLayerParamsToTest);
// Exclude test cases with VK_REMAINING_ARRAY_LAYERS when using vkCmdClearAttachments
const size_t numOfAttachmentLayerParamsToTest = numOfImageLayerParamsToTest - 2;
const VkExtent3D imageDimensions[] =
{
{ 256, 1, 1},
{ 256, 256, 1},
{ 256, 256, 16},
{ 200, 1, 1},
{ 200, 180, 1},
{ 200, 180, 16},
{ 71, 1, 1},
{ 1, 33, 1},
{ 55, 21, 11},
{ 64, 11, 1},
{ 33, 128, 1},
{ 32, 29, 3}
};
// Clear color image
{
const VkImageType imageTypesToTest[] =
{
VK_IMAGE_TYPE_1D,
VK_IMAGE_TYPE_2D,
VK_IMAGE_TYPE_3D
};
const size_t numOfImageTypesToTest = DE_LENGTH_OF_ARRAY(imageTypesToTest);
const VkImageTiling imageTilingsToTest[] =
{
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_TILING_LINEAR,
};
const size_t numOfImageTilingsToTest = DE_LENGTH_OF_ARRAY(imageTilingsToTest);
for (size_t imageTypeIndex = 0; imageTypeIndex < numOfImageTypesToTest; ++imageTypeIndex)
{
de::MovePtr<TestCaseGroup> imageTypeGroup(new TestCaseGroup(testCtx, getImageTypeCaseName(imageTypesToTest[imageTypeIndex]), ""));
for (size_t imageTilingIndex = 0; imageTilingIndex < numOfImageTilingsToTest; ++imageTilingIndex)
{
de::MovePtr<TestCaseGroup> imageTilingGroup(new TestCaseGroup(testCtx, getImageTilingCaseName(imageTilingsToTest[imageTilingIndex]), ""));
for (size_t imageLayerParamsIndex = 0; imageLayerParamsIndex < numOfImageLayerParamsToTest; ++imageLayerParamsIndex)
{
// 3D ARRAY images are not supported
if (imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount > 1u && imageTypesToTest[imageTypeIndex] == VK_IMAGE_TYPE_3D)
continue;
// CUBE images are not tested in clear image tests (they are tested in clear attachment tests)
if (imageLayerParamsToTest[imageLayerParamsIndex].isCube)
continue;
de::MovePtr<TestCaseGroup> imageLayersGroup(new TestCaseGroup(testCtx, imageLayerParamsToTest[imageLayerParamsIndex].testName, ""));
for (size_t imageDimensionsIndex = 0; imageDimensionsIndex < DE_LENGTH_OF_ARRAY(imageDimensions); ++imageDimensionsIndex)
{
const VkExtent3D dimensions = imageDimensions[imageDimensionsIndex];
const std::string dimensionsString = extentToString(dimensions, imageTypesToTest[imageTypeIndex]);
if (imageTypesToTest[imageTypeIndex] == VK_IMAGE_TYPE_1D && dimensions.height > 1)
continue;
if (imageTypesToTest[imageTypeIndex] == VK_IMAGE_TYPE_2D && (dimensions.depth > 1 || dimensions.height == 1))
continue;
if (imageTypesToTest[imageTypeIndex] == VK_IMAGE_TYPE_3D && dimensions.depth == 1)
continue;
for (size_t imageFormatIndex = 0; imageFormatIndex < numOfColorImageFormatsToTest; ++imageFormatIndex)
{
const VkFormat format = colorImageFormatsToTest[imageFormatIndex];
const std::string testCaseName = getFormatCaseName(format) + dimensionsString;
const TestParams testParams =
{
false, // bool useSingleMipLevel;
imageTypesToTest[imageTypeIndex], // VkImageType imageType;
format, // VkFormat imageFormat;
imageTilingsToTest[imageTilingIndex], // VkImageTiling imageTiling;
dimensions, // VkExtent3D imageExtent;
imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount, // deUint32 imageLayerCount;
{
0u,
imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount
}, // LayerRange imageViewLayerRange;
makeClearColorValue(format, 0.2f, 0.1f, 0.7f, 0.8f), // VkClearValue initValue;
{
makeClearColorValue(format, 0.1f, 0.5f, 0.3f, 0.9f), // VkClearValue clearValue[0];
makeClearColorValue(format, 0.3f, 0.6f, 0.2f, 0.7f), // VkClearValue clearValue[1];
},
imageLayerParamsToTest[imageLayerParamsIndex].clearLayerRange, // LayerRange clearLayerRange;
allocationKind, // AllocationKind allocationKind;
false // bool isCube;
};
if (!imageLayerParamsToTest[imageLayerParamsIndex].twoStep)
imageLayersGroup->addChild(new InstanceFactory1<ClearColorImageTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName, "Clear Color Image", testParams));
else
imageLayersGroup->addChild(new InstanceFactory1<TwoStepClearColorImageTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName, "Clear Color Image", testParams));
}
}
imageTilingGroup->addChild(imageLayersGroup.release());
}
imageTypeGroup->addChild(imageTilingGroup.release());
}
colorImageClearTests->addChild(imageTypeGroup.release());
}
imageClearingTests->addChild(colorImageClearTests.release());
}
// Clear depth/stencil image
{
for (size_t imageLayerParamsIndex = 0; imageLayerParamsIndex < numOfImageLayerParamsToTest; ++imageLayerParamsIndex)
{
// CUBE images are not tested in clear image tests (they are tested in clear attachment tests)
if (imageLayerParamsToTest[imageLayerParamsIndex].isCube)
continue;
de::MovePtr<TestCaseGroup> imageLayersGroup(new TestCaseGroup(testCtx, imageLayerParamsToTest[imageLayerParamsIndex].testName, ""));
for (size_t imageDimensionsIndex = 0; imageDimensionsIndex < DE_LENGTH_OF_ARRAY(imageDimensions); ++imageDimensionsIndex)
{
const VkExtent3D dimensions = imageDimensions[imageDimensionsIndex];
const std::string dimensionsString = extentToString(dimensions, VK_IMAGE_TYPE_2D);
if (dimensions.height == 1 || dimensions.depth > 1)
continue;
for (size_t imageFormatIndex = 0; imageFormatIndex < numOfDepthStencilImageFormatsToTest; ++imageFormatIndex)
{
const VkFormat format = depthStencilImageFormatsToTest[imageFormatIndex];
const std::string testCaseName = getFormatCaseName(format) + dimensionsString;
const TestParams testParams =
{
true, // bool useSingleMipLevel;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
format, // VkFormat format;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
dimensions, // VkExtent3D extent;
imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount, // deUint32 imageLayerCount;
{
0u,
imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount
}, // LayerRange imageViewLayerRange;
makeClearValueDepthStencil(0.5f, 0x03), // VkClearValue initValue
{
makeClearValueDepthStencil(0.1f, 0x06), // VkClearValue clearValue[0];
makeClearValueDepthStencil(0.3f, 0x04), // VkClearValue clearValue[1];
},
imageLayerParamsToTest[imageLayerParamsIndex].clearLayerRange, // LayerRange clearLayerRange;
allocationKind, // AllocationKind allocationKind;
false // bool isCube;
};
if (!imageLayerParamsToTest[imageLayerParamsIndex].twoStep)
imageLayersGroup->addChild(new InstanceFactory1<ClearDepthStencilImageTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName, "Clear Depth/Stencil Image", testParams));
else
imageLayersGroup->addChild(new InstanceFactory1<TwoStepClearDepthStencilImageTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName, "Clear Depth/Stencil Image", testParams));
}
}
depthStencilImageClearTests->addChild(imageLayersGroup.release());
}
imageClearingTests->addChild(depthStencilImageClearTests.release());
}
// Clear color attachment
{
for (size_t imageLayerParamsIndex = 0; imageLayerParamsIndex < numOfAttachmentLayerParamsToTest; ++imageLayerParamsIndex)
{
if (!imageLayerParamsToTest[imageLayerParamsIndex].twoStep)
{
de::MovePtr<TestCaseGroup> colorAttachmentClearLayersGroup(new TestCaseGroup(testCtx, imageLayerParamsToTest[imageLayerParamsIndex].testName, ""));
de::MovePtr<TestCaseGroup> partialColorAttachmentClearLayersGroup(new TestCaseGroup(testCtx, imageLayerParamsToTest[imageLayerParamsIndex].testName, ""));
for (size_t imageDimensionsIndex = 0; imageDimensionsIndex < DE_LENGTH_OF_ARRAY(imageDimensions); ++imageDimensionsIndex)
{
const VkExtent3D dimensions = imageDimensions[imageDimensionsIndex];
const std::string dimensionsString = extentToString(dimensions, VK_IMAGE_TYPE_2D);
if (dimensions.height == 1 || dimensions.depth > 1)
continue;
if (imageLayerParamsToTest[imageLayerParamsIndex].isCube && dimensions.width != dimensions.height)
continue;
for (size_t imageFormatIndex = 0; imageFormatIndex < numOfColorImageFormatsToTest; ++imageFormatIndex)
{
const VkFormat format = colorImageFormatsToTest[imageFormatIndex];
const std::string testCaseName = getFormatCaseName(format) + dimensionsString;
const TestParams testParams =
{
true, // bool useSingleMipLevel;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
format, // VkFormat format;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
dimensions, // VkExtent3D extent;
imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount, // deUint32 imageLayerCount;
imageLayerParamsToTest[imageLayerParamsIndex].imageViewRange, // LayerRange imageViewLayerRange;
makeClearColorValue(format, 0.2f, 0.1f, 0.7f, 0.8f), // VkClearValue initValue
{
makeClearColorValue(format, 0.1f, 0.5f, 0.3f, 0.9f), // VkClearValue clearValue[0];
makeClearColorValue(format, 0.3f, 0.6f, 0.2f, 0.7f), // VkClearValue clearValue[1];
},
imageLayerParamsToTest[imageLayerParamsIndex].clearLayerRange, // LayerRange clearLayerRange;
allocationKind, // AllocationKind allocationKind;
imageLayerParamsToTest[imageLayerParamsIndex].isCube // bool isCube;
};
colorAttachmentClearLayersGroup->addChild(new InstanceFactory1<ClearAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName, "Clear Color Attachment", testParams));
if (dimensions.width > 1)
partialColorAttachmentClearLayersGroup->addChild(new InstanceFactory1<PartialClearAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName, "Partial Clear Color Attachment", testParams));
}
}
colorAttachmentClearTests->addChild(colorAttachmentClearLayersGroup.release());
partialColorAttachmentClearTests->addChild(partialColorAttachmentClearLayersGroup.release());
}
}
imageClearingTests->addChild(colorAttachmentClearTests.release());
imageClearingTests->addChild(partialColorAttachmentClearTests.release());
}
// Clear depth/stencil attachment
{
for (size_t imageLayerParamsIndex = 0; imageLayerParamsIndex < numOfAttachmentLayerParamsToTest; ++imageLayerParamsIndex)
{
if (!imageLayerParamsToTest[imageLayerParamsIndex].twoStep)
{
de::MovePtr<TestCaseGroup> depthStencilLayersGroup(new TestCaseGroup(testCtx, imageLayerParamsToTest[imageLayerParamsIndex].testName, ""));
de::MovePtr<TestCaseGroup> partialDepthStencilLayersGroup(new TestCaseGroup(testCtx, imageLayerParamsToTest[imageLayerParamsIndex].testName, ""));
for (size_t imageDimensionsIndex = 0; imageDimensionsIndex < DE_LENGTH_OF_ARRAY(imageDimensions); ++imageDimensionsIndex)
{
const VkExtent3D dimensions = imageDimensions[imageDimensionsIndex];
const std::string dimensionsString = extentToString(dimensions, VK_IMAGE_TYPE_2D);
if (dimensions.height == 1 || dimensions.depth > 1)
continue;
if (imageLayerParamsToTest[imageLayerParamsIndex].isCube && dimensions.width != dimensions.height)
continue;
for (size_t imageFormatIndex = 0; imageFormatIndex < numOfDepthStencilImageFormatsToTest; ++imageFormatIndex)
{
const VkFormat format = depthStencilImageFormatsToTest[imageFormatIndex];
const std::string testCaseName = getFormatCaseName(format) + dimensionsString;
const TestParams testParams =
{
true, // bool useSingleMipLevel;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
format, // VkFormat format;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
dimensions, // VkExtent3D extent;
imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount, // deUint32 imageLayerCount;
imageLayerParamsToTest[imageLayerParamsIndex].imageViewRange, // LayerRange imageViewLayerRange;
makeClearValueDepthStencil(0.5f, 0x03), // VkClearValue initValue
{
makeClearValueDepthStencil(0.1f, 0x06), // VkClearValue clearValue[0];
makeClearValueDepthStencil(0.3f, 0x04), // VkClearValue clearValue[1];
},
imageLayerParamsToTest[imageLayerParamsIndex].clearLayerRange, // LayerRange clearLayerRange;
allocationKind, // AllocationKind allocationKind;
imageLayerParamsToTest[imageLayerParamsIndex].isCube // bool isCube;
};
depthStencilLayersGroup->addChild(new InstanceFactory1<ClearAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName, "Clear Depth/Stencil Attachment", testParams));
if (dimensions.width > 1)
partialDepthStencilLayersGroup->addChild(new InstanceFactory1<PartialClearAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName, "Partial Clear Depth/Stencil Attachment", testParams));
}
}
depthStencilAttachmentClearTests->addChild(depthStencilLayersGroup.release());
partialDepthStencilAttachmentClearTests->addChild(partialDepthStencilLayersGroup.release());
}
}
imageClearingTests->addChild(depthStencilAttachmentClearTests.release());
imageClearingTests->addChild(partialDepthStencilAttachmentClearTests.release());
}
return imageClearingTests;
}
void createCoreImageClearingTests (tcu::TestCaseGroup* group)
{
createImageClearingTestsCommon(group->getTestContext(), group, ALLOCATION_KIND_SUBALLOCATED);
}
void createDedicatedAllocationImageClearingTests (tcu::TestCaseGroup* group)
{
createImageClearingTestsCommon(group->getTestContext(), group, ALLOCATION_KIND_DEDICATED);
}
} // anonymous
TestCaseGroup* createImageClearingTests (TestContext& testCtx)
{
de::MovePtr<TestCaseGroup> imageClearingTests (new TestCaseGroup(testCtx, "image_clearing", "Image Clearing Tests"));
imageClearingTests->addChild(createTestGroup(testCtx, "core", "Core Image Clearing Tests", createCoreImageClearingTests));
imageClearingTests->addChild(createTestGroup(testCtx, "dedicated_allocation", "Image Clearing Tests For Dedicated Memory Allocation", createDedicatedAllocationImageClearingTests));
return imageClearingTests.release();
}
} // api
} // vkt