blob: 749612220294276bb2c8b36cb4ec7dc5713c7297 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2015 The Khronos Group Inc.
* Copyright (c) 2015 Imagination Technologies 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 Sampler Tests
*//*--------------------------------------------------------------------*/
#include "vktPipelineSamplerTests.hpp"
#include "vktPipelineImageSamplingInstance.hpp"
#include "vktPipelineImageUtil.hpp"
#include "vktPipelineVertexUtil.hpp"
#include "vktTestCase.hpp"
#include "vkImageUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkPrograms.hpp"
#include "vkImageWithMemory.hpp"
#include "vkBufferWithMemory.hpp"
#include "tcuPlatform.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuTestLog.hpp"
#include "tcuMaybe.hpp"
#include "deStringUtil.hpp"
#include "deMemory.h"
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <memory>
#include <utility>
#include <algorithm>
namespace vkt
{
namespace pipeline
{
using namespace vk;
using de::MovePtr;
namespace
{
class SamplerViewType
{
public:
SamplerViewType (vk::VkImageViewType type, bool normalized = true)
: m_viewType(type), m_normalized(normalized)
{
if (!normalized)
DE_ASSERT(type == vk::VK_IMAGE_VIEW_TYPE_2D || type == vk::VK_IMAGE_VIEW_TYPE_1D);
}
operator vk::VkImageViewType () const
{
return m_viewType;
}
bool isNormalized () const
{
return m_normalized;
}
private:
vk::VkImageViewType m_viewType;
bool m_normalized;
};
class SamplerTest : public vkt::TestCase
{
public:
SamplerTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
int imageSize,
float samplerLod,
bool separateStencilUsage);
virtual ~SamplerTest (void) {}
virtual ImageSamplingInstanceParams getImageSamplingInstanceParams (SamplerViewType imageViewType,
VkFormat imageFormat,
int imageSize,
float samplerLod,
bool separateStencilUsage) const;
tcu::Vec4 swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const;
virtual void initPrograms (SourceCollections& sourceCollections) const;
virtual void checkSupport (Context& context) const;
virtual TestInstance* createInstance (Context& context) const;
virtual tcu::UVec2 getRenderSize (SamplerViewType viewType) const;
virtual std::vector<Vertex4Tex4> createVertices (void) const;
virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
virtual VkComponentMapping getComponentMapping (void) const;
static std::string getGlslSamplerType (const tcu::TextureFormat& format, SamplerViewType type);
static tcu::IVec3 getImageSize (SamplerViewType viewType, int size);
static int getArraySize (SamplerViewType viewType);
protected:
SamplerViewType m_imageViewType;
VkFormat m_imageFormat;
int m_imageSize;
float m_samplerLod;
bool m_separateStencilUsage;
};
class SamplerMagFilterTest : public SamplerTest
{
public:
SamplerMagFilterTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkFilter magFilter,
bool separateStencilUsage);
virtual ~SamplerMagFilterTest (void) {}
virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
private:
VkFilter m_magFilter;
};
class SamplerMinFilterTest : public SamplerTest
{
public:
SamplerMinFilterTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkFilter minFilter,
bool separateStencilUsage);
virtual ~SamplerMinFilterTest (void) {}
virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
private:
VkFilter m_minFilter;
};
class SamplerMagReduceFilterTest : public SamplerMagFilterTest
{
public:
SamplerMagReduceFilterTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkComponentMapping componentMapping,
VkSamplerReductionMode reductionMode,
bool separateStencilUsage);
virtual ~SamplerMagReduceFilterTest (void) {}
virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
virtual VkComponentMapping getComponentMapping (void) const;
private:
const VkSamplerReductionModeCreateInfo m_reductionCreaterInfo;
VkComponentMapping m_componentMapping;
};
class SamplerMinReduceFilterTest : public SamplerMinFilterTest
{
public:
SamplerMinReduceFilterTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkComponentMapping componentMapping,
VkSamplerReductionMode reductionMode,
bool separateStencilUsage);
virtual ~SamplerMinReduceFilterTest (void) {}
virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
virtual VkComponentMapping getComponentMapping (void) const;
private:
const VkSamplerReductionModeCreateInfo m_reductionCreaterInfo;
VkComponentMapping m_componentMapping;
};
class SamplerLodTest : public SamplerTest
{
public:
SamplerLodTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkSamplerMipmapMode mipmapMode,
float minLod,
float maxLod,
float mipLodBias,
float samplerLod,
bool separateStencilUsage);
virtual ~SamplerLodTest (void) {}
virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
virtual void checkSupport (Context& context) const;
private:
VkSamplerMipmapMode m_mipmapMode;
float m_minLod;
float m_maxLod;
float m_mipLodBias;
};
void SamplerLodTest::checkSupport (Context& context) const
{
SamplerTest::checkSupport(context);
if (m_mipLodBias != 0.0f && context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
!context.getPortabilitySubsetFeatures().samplerMipLodBias)
{
TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Sampler mipmap LOD bias is not supported by this implementation");
}
}
class SamplerAddressModesTest : public SamplerTest
{
public:
SamplerAddressModesTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkSamplerAddressMode addressU,
VkSamplerAddressMode addressV,
VkSamplerAddressMode addressW,
VkBorderColor borderColor,
rr::GenericVec4 customBorderColorValue,
bool customBorderColorFormatless,
bool separateStencilUsage);
virtual ~SamplerAddressModesTest (void) {}
virtual tcu::UVec2 getRenderSize (SamplerViewType viewType) const;
virtual std::vector<Vertex4Tex4> createVertices (void) const;
virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
VkSamplerCustomBorderColorCreateInfoEXT getSamplerCustomBorderColorCreateInfo (VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const;
private:
VkSamplerAddressMode m_addressU;
VkSamplerAddressMode m_addressV;
VkSamplerAddressMode m_addressW;
VkBorderColor m_borderColor;
const VkSamplerCustomBorderColorCreateInfoEXT m_customBorderColorCreateInfo;
};
// SamplerTest
SamplerTest::SamplerTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
int imageSize,
float samplerLod,
bool separateStencilUsage)
: vkt::TestCase (testContext, name, description)
, m_imageViewType (imageViewType)
, m_imageFormat (imageFormat)
, m_imageSize (imageSize)
, m_samplerLod (samplerLod)
, m_separateStencilUsage (separateStencilUsage)
{
}
ImageSamplingInstanceParams SamplerTest::getImageSamplingInstanceParams (SamplerViewType imageViewType,
VkFormat imageFormat,
int imageSize,
float samplerLod,
bool separateStencilUsage) const
{
const tcu::UVec2 renderSize = getRenderSize(imageViewType);
const std::vector<Vertex4Tex4> vertices = createVertices();
const VkSamplerCreateInfo samplerParams = getSamplerCreateInfo();
const VkComponentMapping componentMapping = getComponentMapping();
const VkImageAspectFlags imageAspect = (!isCompressedFormat(imageFormat) && hasDepthComponent(mapVkFormat(imageFormat).order)) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
const deUint32 mipLevels = (imageViewType.isNormalized() ? static_cast<deUint32>(deLog2Floor32(imageSize)) + 1u : 1u);
const VkImageSubresourceRange subresourceRange =
{
imageAspect, // VkImageAspectFlags aspectMask;
0u, // deUint32 baseMipLevel;
mipLevels, // deUint32 mipLevels;
0u, // deUint32 baseArrayLayer;
(deUint32)SamplerTest::getArraySize(imageViewType) // deUint32 arraySize;
};
return ImageSamplingInstanceParams(renderSize, imageViewType, imageFormat,
getImageSize(imageViewType, imageSize),
getArraySize(imageViewType),
componentMapping, subresourceRange,
samplerParams, samplerLod, vertices, separateStencilUsage);
}
void SamplerTest::checkSupport (Context& context) const
{
checkSupportImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_samplerLod, m_separateStencilUsage));
}
tcu::Vec4 SamplerTest::swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const
{
// Remove VK_COMPONENT_SWIZZLE_IDENTITY to avoid addressing channelValues[0]
const vk::VkComponentMapping nonIdentityMapping =
{
componentMapping.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : componentMapping.r,
componentMapping.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : componentMapping.g,
componentMapping.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : componentMapping.b,
componentMapping.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : componentMapping.a
};
// array map with enum VkComponentSwizzle
const float channelValues[] =
{
-1.0f, // impossible
zeroOrOneValue, // SWIZZLE_0
zeroOrOneValue, // SWIZZLE_1
inputData.x(),
inputData.y(),
inputData.z(),
inputData.w(),
-1.0f
};
return tcu::Vec4(channelValues[nonIdentityMapping.r],
channelValues[nonIdentityMapping.g],
channelValues[nonIdentityMapping.b],
channelValues[nonIdentityMapping.a]);
}
void SamplerTest::initPrograms (SourceCollections& sourceCollections) const
{
std::ostringstream vertexSrc;
std::ostringstream fragmentSrc;
const char* texCoordSwizzle = DE_NULL;
tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
: mapVkFormat(m_imageFormat);
tcu::Vec4 lookupScale;
tcu::Vec4 lookupBias;
getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
tcu::Vec4 swizzledScale = swizzle(lookupScale, getComponentMapping(), 1.0f);
tcu::Vec4 swizzledBias = swizzle(lookupBias, getComponentMapping(), 0.0f);
switch (m_imageViewType)
{
case VK_IMAGE_VIEW_TYPE_1D:
texCoordSwizzle = "x";
break;
case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
case VK_IMAGE_VIEW_TYPE_2D:
texCoordSwizzle = "xy";
break;
case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
case VK_IMAGE_VIEW_TYPE_3D:
case VK_IMAGE_VIEW_TYPE_CUBE:
texCoordSwizzle = "xyz";
break;
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
texCoordSwizzle = "xyzw";
break;
default:
DE_ASSERT(false);
break;
}
vertexSrc << "#version 440\n"
<< "layout(location = 0) in vec4 position;\n"
<< "layout(location = 1) in vec4 texCoords;\n"
<< "layout(location = 0) out highp vec4 vtxTexCoords;\n"
<< "out gl_PerVertex {\n"
<< " vec4 gl_Position;\n"
<< "};\n"
<< "void main (void)\n"
<< "{\n"
<< " gl_Position = position;\n"
<< " vtxTexCoords = texCoords;\n"
<< "}\n";
fragmentSrc << "#version 440\n"
<< "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n"
<< "layout(location = 0) in highp vec4 vtxTexCoords;\n"
<< "layout(location = 0) out highp vec4 fragColor;\n"
<< "void main (void)\n"
<< "{\n"
<< " fragColor = ";
if (m_samplerLod > 0.0f)
{
DE_ASSERT(m_imageViewType.isNormalized());
fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")";
}
else
{
fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
}
fragmentSrc << " * vec4" << std::scientific << swizzledScale << " + vec4" << swizzledBias << ";\n"
<< "}\n";
sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
}
TestInstance* SamplerTest::createInstance (Context& context) const
{
return new ImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_samplerLod, m_separateStencilUsage));
}
tcu::UVec2 SamplerTest::getRenderSize (SamplerViewType viewType) const
{
if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
{
return tcu::UVec2(16u, 16u);
}
else
{
return tcu::UVec2(16u * 3u, 16u * 2u);
}
}
std::vector<Vertex4Tex4> SamplerTest::createVertices (void) const
{
std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType);
// Adjust texture coordinate to avoid doing NEAREST filtering exactly on texel boundaries.
// TODO: Would be nice to base this on number of texels and subtexel precision. But this
// seems to work.
for (unsigned int i = 0; i < vertices.size(); ++i) {
vertices[i].texCoord += tcu::Vec4(0.002f, 0.002f, 0.002f, 0.0f);
if (!m_imageViewType.isNormalized()) {
const float imageSize = static_cast<float>(m_imageSize);
for (int j = 0; j < tcu::Vec4::SIZE; ++j)
vertices[i].texCoord[j] *= imageSize;
}
}
return vertices;
}
VkSamplerCreateInfo SamplerTest::getSamplerCreateInfo (void) const
{
const VkSamplerCreateInfo defaultSamplerParams =
{
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkSamplerCreateFlags flags;
VK_FILTER_NEAREST, // VkFilter magFilter;
VK_FILTER_NEAREST, // VkFilter minFilter;
VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
0.0f, // float mipLodBias;
VK_FALSE, // VkBool32 anisotropyEnable;
1.0f, // float maxAnisotropy;
false, // VkBool32 compareEnable;
VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
0.0f, // float minLod;
(m_imageViewType.isNormalized() ? 0.25f : 0.0f), // float maxLod;
getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat), // VkBorderColor borderColor;
!m_imageViewType.isNormalized(), // VkBool32 unnormalizedCoordinates;
};
return defaultSamplerParams;
}
VkComponentMapping SamplerTest::getComponentMapping (void) const
{
const VkComponentMapping componentMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
return componentMapping;
}
std::string SamplerTest::getGlslSamplerType (const tcu::TextureFormat& format, SamplerViewType type)
{
std::ostringstream samplerType;
if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
samplerType << "u";
else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
samplerType << "i";
switch (type)
{
case VK_IMAGE_VIEW_TYPE_1D:
samplerType << "sampler1D";
break;
case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
samplerType << "sampler1DArray";
break;
case VK_IMAGE_VIEW_TYPE_2D:
samplerType << "sampler2D";
break;
case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
samplerType << "sampler2DArray";
break;
case VK_IMAGE_VIEW_TYPE_3D:
samplerType << "sampler3D";
break;
case VK_IMAGE_VIEW_TYPE_CUBE:
samplerType << "samplerCube";
break;
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
samplerType << "samplerCubeArray";
break;
default:
DE_FATAL("Unknown image view type");
break;
}
return samplerType.str();
}
tcu::IVec3 SamplerTest::getImageSize (SamplerViewType viewType, int size)
{
switch (viewType)
{
case VK_IMAGE_VIEW_TYPE_1D:
case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
return tcu::IVec3(size, 1, 1);
case VK_IMAGE_VIEW_TYPE_3D:
return tcu::IVec3(size, size, 4);
default:
break;
}
return tcu::IVec3(size, size, 1);
}
int SamplerTest::getArraySize (SamplerViewType viewType)
{
switch (viewType)
{
case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
case VK_IMAGE_VIEW_TYPE_CUBE:
return 6;
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
return 36;
default:
break;
}
return 1;
}
// SamplerMagFilterTest
SamplerMagFilterTest::SamplerMagFilterTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkFilter magFilter,
bool separateStencilUsage)
: SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f, separateStencilUsage)
, m_magFilter (magFilter)
{
}
VkSamplerCreateInfo SamplerMagFilterTest::getSamplerCreateInfo (void) const
{
VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
samplerParams.magFilter = m_magFilter;
return samplerParams;
}
// SamplerMinFilterTest
SamplerMinFilterTest::SamplerMinFilterTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkFilter minFilter,
bool separateStencilUsage)
: SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, 0.0f, separateStencilUsage)
, m_minFilter (minFilter)
{
}
VkSamplerCreateInfo SamplerMinFilterTest::getSamplerCreateInfo (void) const
{
VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
samplerParams.minFilter = m_minFilter;
// set minLod to epsilon, to force use of the minFilter
samplerParams.minLod = 0.01f;
return samplerParams;
}
namespace
{
VkSamplerReductionModeCreateInfo getSamplerReductionCreateInfo (VkSamplerReductionMode reductionMode)
{
const VkSamplerReductionModeCreateInfo ret =
{
VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
reductionMode // VkSamplerReductionMode reductionMode
};
return ret;
}
}
// SamplerMagReduceFilterTest
SamplerMagReduceFilterTest::SamplerMagReduceFilterTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkComponentMapping componentMapping,
VkSamplerReductionMode reductionMode,
bool separateStencilUsage)
: SamplerMagFilterTest (testContext, name, description, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage)
, m_reductionCreaterInfo (getSamplerReductionCreateInfo(reductionMode))
, m_componentMapping (componentMapping)
{
}
VkSamplerCreateInfo SamplerMagReduceFilterTest::getSamplerCreateInfo (void) const
{
VkSamplerCreateInfo samplerParams = SamplerMagFilterTest::getSamplerCreateInfo();
samplerParams.pNext = &m_reductionCreaterInfo;
return samplerParams;
}
VkComponentMapping SamplerMagReduceFilterTest::getComponentMapping (void) const
{
return m_componentMapping;
}
// SamplerMinReduceFilterTest
SamplerMinReduceFilterTest::SamplerMinReduceFilterTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkComponentMapping componentMapping,
VkSamplerReductionMode reductionMode,
bool separateStencilUsage)
: SamplerMinFilterTest (testContext, name, description, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage)
, m_reductionCreaterInfo (getSamplerReductionCreateInfo(reductionMode))
, m_componentMapping (componentMapping)
{
}
VkSamplerCreateInfo SamplerMinReduceFilterTest::getSamplerCreateInfo (void) const
{
VkSamplerCreateInfo samplerParams = SamplerMinFilterTest::getSamplerCreateInfo();
samplerParams.pNext = &m_reductionCreaterInfo;
return samplerParams;
}
VkComponentMapping SamplerMinReduceFilterTest::getComponentMapping (void) const
{
return m_componentMapping;
}
// SamplerLodTest
SamplerLodTest::SamplerLodTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkSamplerMipmapMode mipmapMode,
float minLod,
float maxLod,
float mipLodBias,
float samplerLod,
bool separateStencilUsage)
: SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, samplerLod, separateStencilUsage)
, m_mipmapMode (mipmapMode)
, m_minLod (minLod)
, m_maxLod (maxLod)
, m_mipLodBias (mipLodBias)
{
}
VkSamplerCreateInfo SamplerLodTest::getSamplerCreateInfo (void) const
{
VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
samplerParams.mipmapMode = m_mipmapMode;
samplerParams.minLod = m_minLod;
samplerParams.maxLod = m_maxLod;
samplerParams.mipLodBias = m_mipLodBias;
return samplerParams;
}
// SamplerAddressModesTest
SamplerAddressModesTest::SamplerAddressModesTest (tcu::TestContext& testContext,
const char* name,
const char* description,
SamplerViewType imageViewType,
VkFormat imageFormat,
VkSamplerAddressMode addressU,
VkSamplerAddressMode addressV,
VkSamplerAddressMode addressW,
VkBorderColor borderColor,
rr::GenericVec4 customBorderColorValue,
bool customBorderColorFormatless,
bool separateStencilUsage)
: SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f, separateStencilUsage)
, m_addressU (addressU)
, m_addressV (addressV)
, m_addressW (addressW)
, m_borderColor (borderColor)
, m_customBorderColorCreateInfo (getSamplerCustomBorderColorCreateInfo(imageFormat, customBorderColorValue, customBorderColorFormatless))
{
}
tcu::UVec2 SamplerAddressModesTest::getRenderSize (SamplerViewType viewType) const
{
return 4u * SamplerTest::getRenderSize(viewType);
}
std::vector<Vertex4Tex4> SamplerAddressModesTest::createVertices (void) const
{
std::vector<Vertex4Tex4> vertices = SamplerTest::createVertices();
switch (m_imageViewType)
{
case VK_IMAGE_VIEW_TYPE_1D: case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
vertices[vertexNdx].texCoord.x() = (vertices[vertexNdx].texCoord.x() - 0.5f) * 4.0f;
break;
case VK_IMAGE_VIEW_TYPE_2D:
case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
vertices[vertexNdx].texCoord.xy() = (vertices[vertexNdx].texCoord.swizzle(0, 1) - tcu::Vec2(0.5f)) * 4.0f;
break;
case VK_IMAGE_VIEW_TYPE_3D:
for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
vertices[vertexNdx].texCoord.xyz() = (vertices[vertexNdx].texCoord.swizzle(0, 1, 2) - tcu::Vec3(0.5f)) * 4.0f;
break;
case VK_IMAGE_VIEW_TYPE_CUBE:
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
break;
default:
DE_ASSERT(false);
}
return vertices;
}
VkSamplerCreateInfo SamplerAddressModesTest::getSamplerCreateInfo (void) const
{
VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
samplerParams.addressModeU = m_addressU;
samplerParams.addressModeV = m_addressV;
samplerParams.addressModeW = m_addressW;
samplerParams.borderColor = m_borderColor;
if (m_borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT ||
m_borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT)
{
samplerParams.pNext = &m_customBorderColorCreateInfo;
}
return samplerParams;
}
VkSamplerCustomBorderColorCreateInfoEXT SamplerAddressModesTest::getSamplerCustomBorderColorCreateInfo (VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const
{
const VkSamplerCustomBorderColorCreateInfoEXT defaultSamplerCustomBorderColorParams =
{
VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
DE_NULL,
mapVkColor(customBorderColorValue),
customBorderColorFormatless ? VK_FORMAT_UNDEFINED : format
};
return defaultSamplerCustomBorderColorParams;
}
// Utilities to create test nodes
std::string getFormatCaseName (const VkFormat format)
{
const std::string fullName = getFormatName(format);
DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
return de::toLower(fullName.substr(10));
}
MovePtr<tcu::TestCaseGroup> createSamplerMagFilterTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
{
MovePtr<tcu::TestCaseGroup> samplerMagFilterTests (new tcu::TestCaseGroup(testCtx, "mag_filter", "Tests for magnification filter"));
if (imageViewType.isNormalized() && (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "linear", "Magnifies image using VK_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage));
samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "nearest", "Magnifies image using VK_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST, separateStencilUsage));
return samplerMagFilterTests;
}
MovePtr<tcu::TestCaseGroup> createSamplerMinFilterTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
{
MovePtr<tcu::TestCaseGroup> samplerMinFilterTests (new tcu::TestCaseGroup(testCtx, "min_filter", "Tests for minification filter"));
if (imageViewType.isNormalized() && (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "linear", "Minifies image using VK_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage));
samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "nearest", "Minifies image using VK_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST, separateStencilUsage));
return samplerMinFilterTests;
}
const VkComponentMapping reduceFilterComponentMappings[] =
{
// filterMinmaxImageComponentMapping == false - compatible mappings:
{ VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO },
{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO },
// other mappings
{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A },
{ VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A },
{ VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R },
};
static std::string getShortComponentSwizzleName (VkComponentSwizzle componentSwizzle)
{
const std::string fullName = getComponentSwizzleName(componentSwizzle);
const char* prefix = "VK_COMPONENT_SWIZZLE_";
DE_ASSERT(de::beginsWith(fullName, prefix));
return de::toLower(fullName.substr(deStrnlen(prefix, -1)));
}
static std::string getComponentMappingGroupName (const VkComponentMapping& componentMapping)
{
std::ostringstream name;
name << "comp_";
name << getShortComponentSwizzleName(componentMapping.r) << "_"
<< getShortComponentSwizzleName(componentMapping.g) << "_"
<< getShortComponentSwizzleName(componentMapping.b) << "_"
<< getShortComponentSwizzleName(componentMapping.a);
return name.str();
}
MovePtr<tcu::TestCaseGroup> createSamplerMagReduceFilterTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
{
MovePtr<tcu::TestCaseGroup> samplerMagReduceFilterTests (new tcu::TestCaseGroup(testCtx, "mag_reduce", "Tests for magnification reduce filter"));
for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
{
const VkComponentMapping& mapping = reduceFilterComponentMappings[i];
MovePtr<tcu::TestCaseGroup> componentGroup (new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str(), "Group for given view component mapping"));
if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
{
componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "average", "Magnifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, separateStencilUsage));
}
componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "min", "Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN_EXT, separateStencilUsage));
componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "max", "Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX_EXT, separateStencilUsage));
samplerMagReduceFilterTests->addChild(componentGroup.release());
}
return samplerMagReduceFilterTests;
}
MovePtr<tcu::TestCaseGroup> createSamplerMinReduceFilterTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
{
MovePtr<tcu::TestCaseGroup> samplerMinReduceFilterTests (new tcu::TestCaseGroup(testCtx, "min_reduce", "Tests for minification reduce filter"));
for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
{
const VkComponentMapping& mapping = reduceFilterComponentMappings[i];
MovePtr<tcu::TestCaseGroup> componentGroup (new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str(), "Group for given view component mapping"));
if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
{
componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "average", "Minifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, separateStencilUsage));
}
componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "min", "Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN_EXT, separateStencilUsage));
componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "max", "Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX_EXT, separateStencilUsage));
samplerMinReduceFilterTests->addChild(componentGroup.release());
}
return samplerMinReduceFilterTests;
}
MovePtr<tcu::TestCaseGroup> createSamplerLodTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode, bool separateStencilUsage)
{
struct TestCaseConfig
{
const char* name;
const char* description;
float minLod;
float maxLod;
float mipLodBias;
float lod;
};
TestCaseConfig testCaseConfigs [] =
{
{ "equal_min_3_max_3", "minLod = 3, maxLod = 3, mipLodBias = 0, lod = 0", 3.0f, 3.0f, 0.0f, 0.0f },
{ "select_min_1", "minLod = 1, maxLod = 5, mipLodBias = 0, lod = 0", 1.0f, 5.0f, 0.0f, 0.0f },
{ "select_max_4", "minLod = 0, maxLod = 4, mipLodBias = 0, lod = 5", 0.0f, 4.0f, 0.0f, 5.0f },
{ "select_bias_2_1", "minLod = 0, maxLod = 2.1, mipLodBias = 5.0, lod = 0", 0.0f, 2.1f, 5.0f, 0.0f },
{ "select_bias_2_5", "minLod = 0, maxLod = 5, mipLodBias = 2.5, lod = 0", 0.0f, 5.0f, 2.5f, 0.00001f },
{ "select_bias_3_1", "minLod = 0, maxLod = 5, mipLodBias = -0.9, lod = 4.0", 0.0f, 5.0f, -0.9f, 4.0f },
{ "select_bias_3_7", "minLod = 0, maxLod = 5, mipLodBias = 3.0, lod = 0.7", 0.0f, 5.0f, 3.0f, 0.7f },
};
MovePtr<tcu::TestCaseGroup> samplerLodTests (new tcu::TestCaseGroup(testCtx, "lod", "Tests for sampler LOD"));
for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
{
const TestCaseConfig& config = testCaseConfigs[configNdx];
samplerLodTests->addChild(new SamplerLodTest(testCtx, config.name, config.description, imageViewType, imageFormat, mipmapMode, config.minLod, config.maxLod, config.mipLodBias, config.lod, separateStencilUsage));
}
return samplerLodTests;
}
MovePtr<tcu::TestCaseGroup> createSamplerMipmapTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
{
MovePtr<tcu::TestCaseGroup> samplerMipmapTests (new tcu::TestCaseGroup(testCtx, "mipmap", "Tests for mipmap modes"));
// Mipmap mode: nearest
MovePtr<tcu::TestCaseGroup> mipmapNearestTests (new tcu::TestCaseGroup(testCtx, "nearest", "Uses VK_TEX_MIPMAP_MODE_NEAREST"));
mipmapNearestTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_NEAREST, separateStencilUsage).release());
samplerMipmapTests->addChild(mipmapNearestTests.release());
// Mipmap mode: linear
if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
{
MovePtr<tcu::TestCaseGroup> mipmapLinearTests(new tcu::TestCaseGroup(testCtx, "linear", "Uses VK_TEX_MIPMAP_MODE_LINEAR"));
mipmapLinearTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_LINEAR, separateStencilUsage).release());
samplerMipmapTests->addChild(mipmapLinearTests.release());
}
return samplerMipmapTests;
}
std::string getAddressModesCaseName (VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w, BorderColor border, tcu::IVec4 customIntValue, bool formatless)
{
static const char* borderColorNames[BORDER_COLOR_COUNT] =
{
"opaque_black",
"opaque_white",
"transparent_black",
"custom"
};
std::ostringstream caseName;
if (u == v && v == w)
{
const std::string fullName = getSamplerAddressModeName(u);
DE_ASSERT(de::beginsWith(fullName, "VK_SAMPLER_ADDRESS_"));
caseName << "all_";
caseName << de::toLower(fullName.substr(19));
if (u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
{
caseName << "_" << borderColorNames[border];
}
}
else
{
const std::string fullNameU = getSamplerAddressModeName(u);
const std::string fullNameV = getSamplerAddressModeName(v);
const std::string fullNameW = getSamplerAddressModeName(w);
DE_ASSERT(de::beginsWith(fullNameU, "VK_SAMPLER_ADDRESS_"));
DE_ASSERT(de::beginsWith(fullNameV, "VK_SAMPLER_ADDRESS_"));
DE_ASSERT(de::beginsWith(fullNameW, "VK_SAMPLER_ADDRESS_"));
caseName << "uvw"
<< "_" << de::toLower(fullNameU.substr(19))
<< "_" << de::toLower(fullNameV.substr(19))
<< "_" << de::toLower(fullNameW.substr(19));
}
if (border == BORDER_COLOR_CUSTOM)
{
caseName << "_";
for (int i = 0; i < 4; i++)
caseName << customIntValue[i];
if (formatless)
caseName << "_formatless";
}
return caseName.str();
}
MovePtr<tcu::TestCaseGroup> createSamplerAddressModesTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
{
struct TestCaseConfig
{
TestCaseConfig (VkSamplerAddressMode _u,
VkSamplerAddressMode _v,
VkSamplerAddressMode _w,
BorderColor _border,
bool _customColorFormatless = false,
tcu::Vec4 _customColorValueFloat = tcu::Vec4(),
tcu::IVec4 _customColorValueInt = tcu::IVec4())
: u(_u), v(_v), w(_w), border(_border), customColorFormatless(_customColorFormatless)
, customColorValueFloat(_customColorValueFloat), customColorValueInt(_customColorValueInt)
{
}
VkSamplerAddressMode u;
VkSamplerAddressMode v;
VkSamplerAddressMode w;
BorderColor border;
bool customColorFormatless;
tcu::Vec4 customColorValueFloat;
tcu::IVec4 customColorValueInt;
};
const TestCaseConfig testCaseConfigs[] =
{
// All address modes equal
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK },
{ VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK },
{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK },
{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK },
// All address modes equal using border color
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_TRANSPARENT_BLACK },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_BLACK },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
// Pairwise combinations of address modes not covered by previous tests
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE},
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
// Custom border color tests
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
false, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::IVec4(0, 0, 0, 0) },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
false, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::IVec4(0, 0, 1, 1) },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
false, tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::IVec4(1, 0, 0, 0) },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
false, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::IVec4(1, 0, 0, 1) },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
false, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), tcu::IVec4(1, 0, 1, 1) },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
false, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::IVec4(1, 1, 0, 1) },
// Custom border color formatless
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
true, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), tcu::IVec4(1, 0, 1, 1) },
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
true, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::IVec4(1, 1, 0, 1) },
};
MovePtr<tcu::TestCaseGroup> samplerAddressModesTests (new tcu::TestCaseGroup(testCtx, "address_modes", "Tests for address modes"));
for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
{
const TestCaseConfig& config = testCaseConfigs[configNdx];
if (!imageViewType.isNormalized() &&
((config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
(config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)))
continue;
// VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16 and VK_FORMAT_B5G5R5A1_UNORM_PACK16 are forbidden
// for non-formatless custom border color.
if ((imageFormat == VK_FORMAT_B4G4R4A4_UNORM_PACK16 ||
imageFormat == VK_FORMAT_B5G6R5_UNORM_PACK16 ||
imageFormat == VK_FORMAT_B5G5R5A1_UNORM_PACK16) && config.border == BORDER_COLOR_CUSTOM && config.customColorFormatless)
continue;
samplerAddressModesTests->addChild(new SamplerAddressModesTest(testCtx,
getAddressModesCaseName(config.u, config.v, config.w, config.border, config.customColorValueInt, config.customColorFormatless).c_str(),
"",
imageViewType,
imageFormat,
config.u, config.v, config.w,
getFormatBorderColor(config.border, imageFormat),
getFormatCustomBorderColor(config.customColorValueFloat, config.customColorValueInt, imageFormat),
config.customColorFormatless,
separateStencilUsage));
}
return samplerAddressModesTests;
}
// Exact sampling case:
// 1) Create a texture and a framebuffer image of the same size.
// 2) Draw a full screen quad with the texture and VK_FILTER_NEAREST.
// 3) Verify the rendered image matches the texture exactly.
class ExactSamplingCase : public vkt::TestCase
{
public:
struct Params
{
vk::VkFormat format;
bool unnormalizedCoordinates;
bool solidColor;
tcu::Maybe<float> offsetSign; // -1.0 or 1.0
};
struct PushConstants
{
float texWidth;
float texHeight;
};
struct VertexData
{
tcu::Vec2 vtxCoords;
tcu::Vec2 texCoords;
static vk::VkVertexInputBindingDescription getBindingDescription (void);
static std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions (void);
};
ExactSamplingCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const Params& params);
virtual ~ExactSamplingCase (void) {}
virtual void initPrograms (vk::SourceCollections& programCollection) const;
virtual TestInstance* createInstance (Context& context) const;
virtual void checkSupport (Context& context) const;
private:
Params m_params;
};
class ExactSamplingInstance : public vkt::TestInstance
{
public:
using Params = ExactSamplingCase::Params;
ExactSamplingInstance (Context& context, const Params& params);
virtual ~ExactSamplingInstance (void) {}
virtual tcu::TestStatus iterate (void);
vk::VkExtent3D getTextureExtent (void) const;
private:
Params m_params;
};
vk::VkVertexInputBindingDescription ExactSamplingCase::VertexData::getBindingDescription (void)
{
static const vk::VkVertexInputBindingDescription desc =
{
0u, // deUint32 binding;
static_cast<deUint32>(sizeof(ExactSamplingCase::VertexData)), // deUint32 stride;
vk::VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
};
return desc;
}
std::vector<vk::VkVertexInputAttributeDescription> ExactSamplingCase::VertexData::getAttributeDescriptions (void)
{
static const std::vector<vk::VkVertexInputAttributeDescription> desc =
{
{
0u, // deUint32 location;
0u, // deUint32 binding;
vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
static_cast<deUint32>(offsetof(ExactSamplingCase::VertexData, vtxCoords)), // deUint32 offset;
},
{
1u, // deUint32 location;
0u, // deUint32 binding;
vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
static_cast<deUint32>(offsetof(ExactSamplingCase::VertexData, texCoords)), // deUint32 offset;
},
};
return desc;
}
ExactSamplingCase::ExactSamplingCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const Params& params)
: vkt::TestCase{testCtx, name, description}, m_params(params)
{
}
void ExactSamplingCase::initPrograms (vk::SourceCollections& programCollection) const
{
std::ostringstream vertexShader;
std::string texCoordX = "inTexCoord.x";
std::string texCoordY = "inTexCoord.y";
if (m_params.unnormalizedCoordinates)
{
texCoordX += " * pushc.texWidth";
texCoordY += " * pushc.texHeight";
}
vertexShader
<< "#version 450\n"
<< "\n"
<< "layout(push_constant, std430) uniform PushConstants\n"
<< "{\n"
<< " float texWidth;\n"
<< " float texHeight;\n"
<< "} pushc;\n"
<< "\n"
<< "layout(location = 0) in vec2 inPosition;\n"
<< "layout(location = 1) in vec2 inTexCoord;\n"
<< "\n"
<< "layout(location = 0) out vec2 fragTexCoord;\n"
<< "\n"
<< "void main() {\n"
<< " gl_Position = vec4(inPosition, 0.0, 1.0);\n"
<< " fragTexCoord = vec2(" << texCoordX << ", " << texCoordY << ");\n"
<< "}\n"
;
programCollection.glslSources.add("vert") << glu::VertexSource{vertexShader.str()};
std::ostringstream fragmentShader;
std::string typePrefix;
if (vk::isIntFormat(m_params.format))
typePrefix = "i";
else if (vk::isUintFormat(m_params.format))
typePrefix = "u";
const std::string samplerType = typePrefix + "sampler2D";
const std::string colorType = typePrefix + "vec4";
fragmentShader
<< "#version 450\n"
<< "\n"
<< "layout(set = 0, binding = 0) uniform " << samplerType << " texSampler;\n"
<< "\n"
<< "layout(location = 0) in vec2 fragTexCoord;\n"
<< "\n"
<< "layout(location = 0) out " << colorType << " outColor;\n"
<< "\n"
<< "void main() {\n"
<< " outColor = texture(texSampler, fragTexCoord);\n"
<< "}\n"
;
programCollection.glslSources.add("frag") << glu::FragmentSource{fragmentShader.str()};
}
TestInstance* ExactSamplingCase::createInstance (Context& context) const
{
return new ExactSamplingInstance{context, m_params};
}
void ExactSamplingCase::checkSupport (Context& context) const
{
const auto& vki = context.getInstanceInterface();
const auto physicalDevice = context.getPhysicalDevice();
const auto props = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, m_params.format);
const vk::VkFormatFeatureFlags requiredFeatures =
(vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT
|vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
|vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
|(m_params.solidColor ? vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT : 0)
);
if ((props.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
TCU_THROW(NotSupportedError, "Selected format does not support the required features");
}
ExactSamplingInstance::ExactSamplingInstance (Context& context, const Params& params)
: vkt::TestInstance{context}, m_params(params)
{
}
vk::VkExtent3D ExactSamplingInstance::getTextureExtent (void) const
{
return vk::makeExtent3D(256u, 256u, 1u);
}
tcu::TestStatus ExactSamplingInstance::iterate (void)
{
const auto& vki = m_context.getInstanceInterface();
const auto physDevice = m_context.getPhysicalDevice();
const auto& vkd = m_context.getDeviceInterface();
const auto device = m_context.getDevice();
auto& allocator = m_context.getDefaultAllocator();
const auto queue = m_context.getUniversalQueue();
const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
const auto tcuFormat = vk::mapVkFormat(m_params.format);
const auto formatInfo = tcu::getTextureFormatInfo(tcuFormat);
const auto texExtent = getTextureExtent();
const auto texUsage = (vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT);
const auto fbUsage = (vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
const auto descType = vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
const auto texLayout = vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
const bool& unnorm = m_params.unnormalizedCoordinates;
// Some code below depends on this.
DE_ASSERT(texExtent.depth == 1u);
const vk::VkImageCreateInfo texImgCreateInfo =
{
vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkImageCreateFlags flags;
vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_params.format, // VkFormat format;
texExtent, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
texUsage, // VkImageUsageFlags usage;
vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&queueIndex, // const deUint32* pQueueFamilyIndices;
vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
};
const vk::VkImageCreateInfo fbImgCreateInfo =
{
vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkImageCreateFlags flags;
vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_params.format, // VkFormat format;
texExtent, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
fbUsage, // VkImageUsageFlags usage;
vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&queueIndex, // const deUint32* pQueueFamilyIndices;
vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
};
// Create main and framebuffer images.
const vk::ImageWithMemory texImage {vkd, device, allocator, texImgCreateInfo, vk::MemoryRequirement::Any};
const vk::ImageWithMemory fbImage {vkd, device, allocator, fbImgCreateInfo, vk::MemoryRequirement::Any};
// Corresponding image views.
const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
const auto texView = vk::makeImageView(vkd, device, texImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format, colorSubresourceRange);
const auto fbView = vk::makeImageView(vkd, device, fbImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format, colorSubresourceRange);
// Buffers to create the texture and verify results.
const vk::VkDeviceSize texBufferSize = static_cast<vk::VkDeviceSize>(static_cast<deUint32>(tcu::getPixelSize(tcuFormat)) * texExtent.width * texExtent.height * texExtent.depth);
const auto texBufferInfo = vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
const auto resultsBufferInfo = vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
const vk::BufferWithMemory texBuffer {vkd, device, allocator, texBufferInfo, vk::MemoryRequirement::HostVisible};
const vk::BufferWithMemory resultsBuffer {vkd, device, allocator, resultsBufferInfo, vk::MemoryRequirement::HostVisible};
// Create texture.
const tcu::IVec2 iImgSize {static_cast<int>(texExtent.width), static_cast<int>(texExtent.height)};
auto& texBufferAlloc = texBuffer.getAllocation();
auto texBufferPtr = reinterpret_cast<char*>(texBufferAlloc.getHostPtr()) + texBufferAlloc.getOffset();
const tcu::PixelBufferAccess texPixels {tcuFormat, iImgSize[0], iImgSize[1], 1, texBufferPtr};
const int W = texPixels.getWidth();
const int H = texPixels.getHeight();
const int D = texPixels.getDepth();
const float divX = static_cast<float>(W - 1);
const float divY = static_cast<float>(H - 1);
tcu::Vec4 texColor;
for (int x = 0; x < W; ++x)
for (int y = 0; y < H; ++y)
for (int z = 0; z < D; ++z)
{
if (m_params.solidColor)
{
// Texture with solid color for filtered sampling.
texColor = tcu::Vec4{0.5f, 0.25f, 0.7529411764705882f, 1.0f};
}
else
{
// Use a color gradient otherwise.
const float colorX = static_cast<float>(x) / divX;
const float colorY = static_cast<float>(y) / divY;
const float colorZ = std::min(colorX, colorY);
texColor = tcu::Vec4{colorX, colorY, colorZ, 1.0f};
}
const tcu::Vec4 finalColor = (texColor - formatInfo.lookupBias) / formatInfo.lookupScale;
texPixels.setPixel(finalColor, x, y, z);
}
vk::flushAlloc(vkd, device, texBufferAlloc);
float minU = 0.0f;
float maxU = 1.0f;
float minV = 0.0f;
float maxV = 1.0f;
// When testing the edges, apply a texture offset of almost half a texel, so the sample location is very close to the texel border.
if (m_params.offsetSign)
{
const float sign = m_params.offsetSign.get(); DE_ASSERT(sign == 1.0f || sign == -1.0f);
const float offsetWidth = 0.499f / static_cast<float>(texExtent.width);
const float offsetHeight = 0.499f / static_cast<float>(texExtent.height);
minU += sign * offsetWidth;
maxU += sign * offsetWidth;
minV += sign * offsetHeight;
maxV += sign * offsetHeight;
}
const std::vector<ExactSamplingCase::VertexData> fullScreenQuad =
{
{{ 1.f, -1.f }, { maxU, minV }, },
{{ -1.f, -1.f }, { minU, minV }, },
{{ -1.f, 1.f }, { minU, maxV }, },
{{ -1.f, 1.f }, { minU, maxV }, },
{{ 1.f, -1.f }, { maxU, minV }, },
{{ 1.f, 1.f }, { maxU, maxV }, },
};
// Vertex buffer.
const vk::VkDeviceSize vertexBufferSize = static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
const auto vertexBufferInfo = vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
const vk::BufferWithMemory vertexBuffer {vkd, device, allocator, vertexBufferInfo, vk::MemoryRequirement::HostVisible};
// Copy data to vertex buffer.
const auto& vertexAlloc = vertexBuffer.getAllocation();
const auto vertexDataPtr = reinterpret_cast<char*>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
vk::flushAlloc(vkd, device, vertexAlloc);
// Descriptor set layout.
vk::DescriptorSetLayoutBuilder layoutBuilder;
layoutBuilder.addSingleBinding(descType, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
// Descriptor pool.
vk::DescriptorPoolBuilder poolBuilder;
poolBuilder.addType(descType);
const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
// Descriptor set.
const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
// Texture sampler. When using a solid color, test linear filtering. Linear filtering may incur in a small precission loss, but
// it should be minimal and we should get the same color when converting back to the original format. Anisotropy should be
// irrelevant too, so it is enabled and set to the maximum level if available.
const auto minMagFilter = (m_params.solidColor ? vk::VK_FILTER_LINEAR : vk::VK_FILTER_NEAREST);
const bool anisotropySupported = (vk::getPhysicalDeviceFeatures(vki, physDevice).samplerAnisotropy == VK_TRUE);
const bool anisotropyEnable = (!unnorm && m_params.solidColor && anisotropySupported);
const float maxAnisotropy = (anisotropyEnable ? vk::getPhysicalDeviceProperties(vki, physDevice).limits.maxSamplerAnisotropy : 1.0f);
const auto addressMode = (unnorm ? vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : vk::VK_SAMPLER_ADDRESS_MODE_REPEAT);
const auto unnormalizedCoordinates = (unnorm ? VK_TRUE : VK_FALSE);
const vk::VkSamplerCreateInfo samplerCreateInfo =
{
vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkSamplerCreateFlags flags;
minMagFilter, // VkFilter magFilter;
minMagFilter, // VkFilter minFilter;
vk::VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
addressMode, // VkSamplerAddressMode addressModeU;
addressMode, // VkSamplerAddressMode addressModeV;
addressMode, // VkSamplerAddressMode addressModeW;
0.0f, // float mipLodBias;
(anisotropyEnable ? VK_TRUE : VK_FALSE), // VkBool32 anisotropyEnable;
maxAnisotropy, // float maxAnisotropy;
VK_FALSE, // VkBool32 compareEnable;
vk::VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
0.0f, // float minLod;
0.0f, // float maxLod;
vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
unnormalizedCoordinates, // VkBool32 unnormalizedCoordinates;
};
const auto texSampler = vk::createSampler(vkd, device, &samplerCreateInfo);
// Update descriptor set with the descriptor.
vk::DescriptorSetUpdateBuilder updateBuilder;
const auto descriptorImageInfo = vk::makeDescriptorImageInfo(texSampler.get(), texView.get(), texLayout);
updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), descType, &descriptorImageInfo);
updateBuilder.update(vkd, device);
// Shader modules.
const auto vertexModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
const auto fragModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
// Render pass.
const vk::VkAttachmentDescription fbAttachment =
{
0u, // VkAttachmentDescriptionFlags flags;
m_params.format, // VkFormat format;
vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
};
const vk::VkAttachmentReference colorRef =
{
0u, // deUint32 attachment;
vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
};
const vk::VkSubpassDescription subpass =
{
0u, // VkSubpassDescriptionFlags flags;
vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
0u, // deUint32 inputAttachmentCount;
nullptr, // const VkAttachmentReference* pInputAttachments;
1u, // deUint32 colorAttachmentCount;
&colorRef, // const VkAttachmentReference* pColorAttachments;
0u, // const VkAttachmentReference* pResolveAttachments;
nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
0u, // deUint32 preserveAttachmentCount;
nullptr, // const deUint32* pPreserveAttachments;
};
const vk::VkRenderPassCreateInfo renderPassInfo =
{
vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkRenderPassCreateFlags flags;
1u, // deUint32 attachmentCount;
&fbAttachment, // const VkAttachmentDescription* pAttachments;
1u, // deUint32 subpassCount;
&subpass, // const VkSubpassDescription* pSubpasses;
0u, // deUint32 dependencyCount;
nullptr, // const VkSubpassDependency* pDependencies;
};
const auto renderPass = vk::createRenderPass(vkd, device, &renderPassInfo);
// Framebuffer.
std::vector<vk::VkImageView> attachments;
attachments.push_back(fbView.get());
const auto framebuffer = vk::makeFramebuffer(vkd, device, renderPass.get(), 1u, &fbView.get(), texExtent.width, texExtent.height, texExtent.depth);
// Push constant range.
const vk::VkPushConstantRange pcRange =
{
vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
0u, // deUint32 offset;
static_cast<deUint32>(sizeof(ExactSamplingCase::PushConstants)), // deUint32 size;
};
// Pipeline layout.
const vk::VkPipelineLayoutCreateInfo pipelineLayoutInfo =
{
vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkPipelineLayoutCreateFlags flags;
1u, // deUint32 setLayoutCount;
&descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
1u, // deUint32 pushConstantRangeCount;
&pcRange, // const VkPushConstantRange* pPushConstantRanges;
};
const auto pipelineLayout = vk::createPipelineLayout(vkd, device, &pipelineLayoutInfo);
// Graphics pipeline.
const std::vector<vk::VkViewport> viewports (1u, vk::makeViewport(texExtent));
const vk::VkRect2D renderArea = vk::makeRect2D(texExtent);
const std::vector<vk::VkRect2D> scissors (1u, renderArea);
const auto vtxBindingDescription = ExactSamplingCase::VertexData::getBindingDescription();
const auto vtxAttributeDescriptions = ExactSamplingCase::VertexData::getAttributeDescriptions();
const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo =
{
vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
nullptr, // const void* pNext
0u, // VkPipelineVertexInputStateCreateFlags flags
1u, // deUint32 vertexBindingDescriptionCount
&vtxBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
static_cast<deUint32>(vtxAttributeDescriptions.size()), // deUint32 vertexAttributeDescriptionCount
vtxAttributeDescriptions.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
};
const auto pipeline = vk::makeGraphicsPipeline(
vkd, device, pipelineLayout.get(),
vertexModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
renderPass.get(), viewports, scissors,
vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u, &vertexInputInfo);
// Command pool and command buffer.
const auto cmdPool = vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
const auto cmdBuffer = cmdBufferPtr.get();
// Draw quad.
const ExactSamplingCase::PushConstants pushConstants =
{
static_cast<float>(texExtent.width),
static_cast<float>(texExtent.height),
};
const tcu::Vec4 clearFbColor (0.0f, 0.0f, 0.0f, 1.0f);
const vk::VkDeviceSize vertexBufferOffset = 0ull;
const auto vertexBufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, vertexBuffer.get(), 0ull, vertexBufferSize);
const auto preBufferCopyBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, texBuffer.get(), 0ull, texBufferSize);
const auto preTexCopyBarrier = vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texImage.get(), colorSubresourceRange);
const auto postTexCopyBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texLayout, texImage.get(), colorSubresourceRange);
const auto texCopyRange = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
const auto texImageCopy = vk::makeBufferImageCopy(texExtent, texCopyRange);
vk::beginCommandBuffer(vkd, cmdBuffer);
vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u, nullptr, 1u, &vertexBufferBarrier, 0u, nullptr);
vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 1u, &preBufferCopyBarrier, 0u, nullptr);
vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preTexCopyBarrier);
vkd.cmdCopyBufferToImage(cmdBuffer, texBuffer.get(), texImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &texImageCopy);
vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &postTexCopyBarrier);
vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea, clearFbColor);
vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), vk::VK_SHADER_STAGE_VERTEX_BIT, 0u, static_cast<deUint32>(sizeof(pushConstants)), &pushConstants);
vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);
vk::endRenderPass(vkd, cmdBuffer);
vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), iImgSize);
vk::endCommandBuffer(vkd, cmdBuffer);
vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
// Check results.
const auto& resultsBufferAlloc = resultsBuffer.getAllocation();
vk::invalidateAlloc(vkd, device, resultsBufferAlloc);
const auto resultsBufferPtr = reinterpret_cast<const char*>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
const tcu::ConstPixelBufferAccess resultPixels {tcuFormat, iImgSize[0], iImgSize[1], 1, resultsBufferPtr};
const tcu::TextureFormat diffFormat {tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8};
const auto diffBytes = tcu::getPixelSize(diffFormat) * iImgSize[0] * iImgSize[1];
std::unique_ptr<deUint8[]> diffData {new deUint8[diffBytes]};
const tcu::PixelBufferAccess diffImg {diffFormat, iImgSize[0], iImgSize[1], 1, diffData.get()};
const tcu::Vec4 colorRed {1.0f, 0.0f, 0.0f, 1.0f};
const tcu::Vec4 colorGreen {0.0f, 1.0f, 0.0f, 1.0f};
// Clear diff image.
deMemset(diffData.get(), 0, static_cast<size_t>(diffBytes));
bool pass = true;
for (int x = 0; x < W; ++x)
for (int y = 0; y < H; ++y)
for (int z = 0; z < D; ++z)
{
const auto inPix = texPixels.getPixel(x, y, z);
const auto outPix = resultPixels.getPixel(x, y, z);
if (inPix == outPix)
{
diffImg.setPixel(colorGreen, x, y, z);
}
else
{
pass = false;
diffImg.setPixel(colorRed, x, y, z);
}
}
tcu::TestStatus status = tcu::TestStatus::pass("Pass");
if (!pass)
{
auto& log = m_context.getTestContext().getLog();
log << tcu::TestLog::Image("input", "Input texture", texPixels);
log << tcu::TestLog::Image("output", "Rendered image", resultPixels);
log << tcu::TestLog::Image("diff", "Mismatched pixels in red", diffImg);
status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
}
return status;
}
} // anonymous
tcu::TestCaseGroup* createAllFormatsSamplerTests (tcu::TestContext& testCtx, bool separateStencilUsage = false)
{
const struct
{
SamplerViewType type;
const char* name;
}
imageViewTypes[] =
{
{ VK_IMAGE_VIEW_TYPE_1D, "1d" },
{ { VK_IMAGE_VIEW_TYPE_1D, false }, "1d_unnormalized" },
{ VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" },
{ VK_IMAGE_VIEW_TYPE_2D, "2d" },
{ { VK_IMAGE_VIEW_TYPE_2D, false }, "2d_unnormalized" },
{ VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" },
{ VK_IMAGE_VIEW_TYPE_3D, "3d" },
{ VK_IMAGE_VIEW_TYPE_CUBE, "cube" },
{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" }
};
const VkFormat formats[] =
{
// Packed formats
VK_FORMAT_R4G4_UNORM_PACK8,
VK_FORMAT_R4G4B4A4_UNORM_PACK16,
VK_FORMAT_R5G6B5_UNORM_PACK16,
VK_FORMAT_R5G5B5A1_UNORM_PACK16,
VK_FORMAT_A2B10G10R10_UNORM_PACK32,
VK_FORMAT_A2R10G10B10_UINT_PACK32,
VK_FORMAT_B10G11R11_UFLOAT_PACK32,
VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
VK_FORMAT_B4G4R4A4_UNORM_PACK16,
VK_FORMAT_B5G5R5A1_UNORM_PACK16,
VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
// Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order
VK_FORMAT_R8_SRGB,
VK_FORMAT_R8G8B8_UINT,
VK_FORMAT_B8G8R8A8_SINT,
VK_FORMAT_R8G8_UNORM,
VK_FORMAT_B8G8R8_SNORM,
VK_FORMAT_R8G8B8A8_SNORM,
VK_FORMAT_R8G8_UINT,
VK_FORMAT_R8_SINT,
VK_FORMAT_R8G8B8A8_SRGB,
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_B8G8R8_SRGB,
VK_FORMAT_R8G8_SRGB,
VK_FORMAT_R8_UINT,
VK_FORMAT_R8G8B8A8_UINT,
VK_FORMAT_R8G8_SINT,
VK_FORMAT_R8_SNORM,
VK_FORMAT_B8G8R8_SINT,
VK_FORMAT_R8G8_SNORM,
VK_FORMAT_B8G8R8_UNORM,
VK_FORMAT_R8_UNORM,
// Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels
VK_FORMAT_R32G32_SFLOAT,
VK_FORMAT_R32G32B32_UINT,
VK_FORMAT_R16G16B16A16_SFLOAT,
VK_FORMAT_R16G16_UINT,
VK_FORMAT_R32G32B32A32_SINT,
VK_FORMAT_R16G16B16_SINT,
VK_FORMAT_R16_SFLOAT,
VK_FORMAT_R32_SINT,
VK_FORMAT_R32_UINT,
VK_FORMAT_R16G16B16_SFLOAT,
VK_FORMAT_R16G16_SINT,
// More 16/32-bit formats required for testing VK_EXT_sampler_filter_minmax
VK_FORMAT_R16_SNORM,
VK_FORMAT_R32_SFLOAT,
// Scaled formats
VK_FORMAT_R8G8B8A8_SSCALED,
VK_FORMAT_A2R10G10B10_USCALED_PACK32,
// Compressed formats
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_5x4_SRGB_BLOCK,
VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
// Depth formats required for testing VK_EXT_sampler_filter_minmax
VK_FORMAT_D16_UNORM,
VK_FORMAT_X8_D24_UNORM_PACK32,
VK_FORMAT_D32_SFLOAT,
VK_FORMAT_D16_UNORM_S8_UINT,
VK_FORMAT_D24_UNORM_S8_UINT,
VK_FORMAT_D32_SFLOAT_S8_UINT,
};
de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type", ""));
for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
{
const SamplerViewType viewType = imageViewTypes[viewTypeNdx].type;
de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str()));
de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Tests samplable formats"));
for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
{
const VkFormat format = formats[formatNdx];
const bool isCompressed = isCompressedFormat(format);
const bool isDepthStencil = !isCompressed
&& tcu::hasDepthComponent(mapVkFormat(format).order) && tcu::hasStencilComponent(mapVkFormat(format).order);
if (isCompressed)
{
// Do not use compressed formats with 1D and 1D array textures.
if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
break;
}
if (separateStencilUsage && !isDepthStencil)
continue;
de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx,
getFormatCaseName(format).c_str(),
(std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
if (!isCompressed && viewType.isNormalized())
{
// Do not include minFilter tests with compressed formats.
// Randomly generated compressed textures are too noisy and will derive in false positives.
de::MovePtr<tcu::TestCaseGroup> minFilterTests = createSamplerMinFilterTests(testCtx, viewType, format, separateStencilUsage);
de::MovePtr<tcu::TestCaseGroup> minReduceFilterTests = createSamplerMinReduceFilterTests(testCtx, viewType, format, separateStencilUsage);
formatGroup->addChild(minFilterTests.release());
formatGroup->addChild(minReduceFilterTests.release());
}
de::MovePtr<tcu::TestCaseGroup> magFilterTests = createSamplerMagFilterTests(testCtx, viewType, format, separateStencilUsage);
formatGroup->addChild(magFilterTests.release());
if (viewType.isNormalized())
{
de::MovePtr<tcu::TestCaseGroup> magReduceFilterTests = createSamplerMagReduceFilterTests(testCtx, viewType, format, separateStencilUsage);
de::MovePtr<tcu::TestCaseGroup> mipmapTests = createSamplerMipmapTests(testCtx, viewType, format, separateStencilUsage);
formatGroup->addChild(magReduceFilterTests.release());
formatGroup->addChild(mipmapTests.release());
}
if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
{
de::MovePtr<tcu::TestCaseGroup> addressModesTests = createSamplerAddressModesTests(testCtx, viewType, format, separateStencilUsage);
formatGroup->addChild(addressModesTests.release());
}
formatTests->addChild(formatGroup.release());
}
viewTypeGroup->addChild(formatTests.release());
viewTypeTests->addChild(viewTypeGroup.release());
}
return viewTypeTests.release();
}
tcu::TestCaseGroup* createExactSamplingTests (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> exactSamplingTests(new tcu::TestCaseGroup(testCtx, "exact_sampling", "Exact sampling tests"));
static const std::vector<vk::VkFormat> formats =
{
vk::VK_FORMAT_R8_SRGB,
vk::VK_FORMAT_R8G8B8_UINT,
vk::VK_FORMAT_B8G8R8A8_SINT,
vk::VK_FORMAT_R8G8_UNORM,
vk::VK_FORMAT_B8G8R8_SNORM,
vk::VK_FORMAT_R8G8B8A8_SNORM,
vk::VK_FORMAT_R8G8_UINT,
vk::VK_FORMAT_R8_SINT,
vk::VK_FORMAT_R8G8B8A8_SRGB,
vk::VK_FORMAT_R8G8B8A8_UNORM,
vk::VK_FORMAT_B8G8R8A8_UNORM,
vk::VK_FORMAT_B8G8R8_SRGB,
vk::VK_FORMAT_R8G8_SRGB,
vk::VK_FORMAT_R8_UINT,
vk::VK_FORMAT_R8G8B8A8_UINT,
vk::VK_FORMAT_R8G8_SINT,
vk::VK_FORMAT_R8_SNORM,
vk::VK_FORMAT_B8G8R8_SINT,
vk::VK_FORMAT_R8G8_SNORM,
vk::VK_FORMAT_B8G8R8_UNORM,
vk::VK_FORMAT_R8_UNORM,
vk::VK_FORMAT_R32G32_SFLOAT,
vk::VK_FORMAT_R32G32B32_UINT,
vk::VK_FORMAT_R16G16B16A16_SFLOAT,
vk::VK_FORMAT_R16G16_UINT,
vk::VK_FORMAT_R32G32B32A32_SINT,
vk::VK_FORMAT_R16G16B16_SINT,
vk::VK_FORMAT_R16_SFLOAT,
vk::VK_FORMAT_R32_SINT,
vk::VK_FORMAT_R32_UINT,
vk::VK_FORMAT_R16G16B16_SFLOAT,
vk::VK_FORMAT_R16G16_SINT,
vk::VK_FORMAT_R16_SNORM,
vk::VK_FORMAT_R32_SFLOAT,
};
static const struct
{
const bool unnormalized;
const std::string name;
const std::string desc;
} unnormalizedCoordinates[] =
{
{ false, "normalized_coords", "Normalized coordinates" },
{ true, "unnormalized_coords", "Unnormalized coordinates" },
};
static const struct
{
const tcu::Maybe<float> offset;
const std::string name;
const std::string desc;
} testEdges[] =
{
{ tcu::nothing<float>(), "centered", "Sampling points centered in texel" },
{ tcu::just<float>(-1.0f), "edge_left", "Sampling points near left edge" },
{ tcu::just<float>(+1.0f), "edge_right", "Sampling points near right edge" },
};
static const std::vector<std::pair<bool, std::string>> solidColor =
{
{ false, "gradient" },
{ true, "solid_color" },
};
for (const auto format : formats)
{
const std::string formatName = getFormatCaseName(format);
const std::string description = std::string("Exact sampling tests with image format ") + getFormatName(format);
de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), description.c_str()));
for (const auto& solid : solidColor)
{
de::MovePtr<tcu::TestCaseGroup> solidColorGroup(new tcu::TestCaseGroup(testCtx, solid.second.c_str(), ""));
for (int unIdx = 0; unIdx < DE_LENGTH_OF_ARRAY(unnormalizedCoordinates); ++unIdx)
{
const auto& unnorm = unnormalizedCoordinates[unIdx];
de::MovePtr<tcu::TestCaseGroup> coordGroup (new tcu::TestCaseGroup(testCtx, unnorm.name.c_str(), unnorm.desc.c_str()));
for (int edgeIdx = 0; edgeIdx < DE_LENGTH_OF_ARRAY(testEdges); ++edgeIdx)
{
const auto& edges = testEdges[edgeIdx];
const ExactSamplingCase::Params params = { format, unnorm.unnormalized, solid.first, edges.offset };
coordGroup->addChild(new ExactSamplingCase{testCtx, edges.name, edges.desc, params});
}
solidColorGroup->addChild(coordGroup.release());
}
formatGroup->addChild(solidColorGroup.release());
}
exactSamplingTests->addChild(formatGroup.release());
}
return exactSamplingTests.release();
}
tcu::TestCaseGroup* createSamplerTests (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> samplerTests(new tcu::TestCaseGroup(testCtx, "sampler", "Sampler tests"));
{
samplerTests->addChild(createAllFormatsSamplerTests(testCtx));
samplerTests->addChild(createExactSamplingTests(testCtx));
}
// tests for VK_EXT_separate_stencil_usage
de::MovePtr<tcu::TestCaseGroup> separateStencilUsageSamplerTests (new tcu::TestCaseGroup(testCtx, "separate_stencil_usage", "testing VK_EXT_separate_stencil_uasge"));
{
separateStencilUsageSamplerTests->addChild(createAllFormatsSamplerTests(testCtx, true));
samplerTests->addChild(separateStencilUsageSamplerTests.release());
}
return samplerTests.release();
}
} // pipeline
} // vkt