blob: ab03a359e7f14dde74d48d00081217519a7cc27d [file] [log] [blame]
/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2017 Google Inc.
*
* 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 SPIR-V Assembly Tests for images and samplers.
*//*--------------------------------------------------------------------*/
#include "vktSpvAsmImageSamplerTests.hpp"
#include "vktSpvAsmComputeShaderCase.hpp"
#include "vktSpvAsmComputeShaderTestUtil.hpp"
#include "vktSpvAsmGraphicsShaderTestUtil.hpp"
#include "vkImageUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVectorUtil.hpp"
namespace vkt
{
namespace SpirVAssembly
{
using namespace vk;
using std::map;
using std::string;
using std::vector;
using tcu::IVec3;
using tcu::RGBA;
using tcu::Vec4;
namespace
{
enum TestType
{
TESTTYPE_LOCAL_VARIABLES = 0,
TESTTYPE_PASS_IMAGE_TO_FUNCTION,
TESTTYPE_PASS_SAMPLER_TO_FUNCTION,
TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION,
TESTTYPE_OPTYPEIMAGE_MISMATCH,
TESTTYPE_LAST
};
enum ReadOp
{
READOP_IMAGEREAD = 0,
READOP_IMAGEFETCH,
READOP_IMAGESAMPLE,
READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD,
READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD,
READOP_LAST
};
enum DescriptorType
{
DESCRIPTOR_TYPE_STORAGE_IMAGE = 0, // Storage image
DESCRIPTOR_TYPE_SAMPLED_IMAGE, // Sampled image
DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // Combined image sampler
DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES, // Combined image sampler with separate shader variables
DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS, // Combined image sampler where image and sampler variables are taken from two different desciptors
DESCRIPTOR_TYPE_LAST
};
enum DepthProperty
{
DEPTH_PROPERTY_NON_DEPTH = 0,
DEPTH_PROPERTY_DEPTH,
DEPTH_PROPERTY_UNKNOWN,
DEPTH_PROPERTY_LAST
};
bool isValidTestCase(TestType testType, DescriptorType descriptorType, ReadOp readOp)
{
// Check valid descriptor type and test type combinations
switch (testType)
{
case TESTTYPE_PASS_IMAGE_TO_FUNCTION:
if (descriptorType != DESCRIPTOR_TYPE_STORAGE_IMAGE && descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
return false;
break;
case TESTTYPE_PASS_SAMPLER_TO_FUNCTION:
if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
return false;
break;
case TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION:
if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
return false;
break;
default:
break;
}
// Check valid descriptor type and read operation combinations
switch (readOp)
{
case READOP_IMAGEREAD:
if (descriptorType != DESCRIPTOR_TYPE_STORAGE_IMAGE)
return false;
break;
case READOP_IMAGEFETCH:
if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
return false;
break;
case READOP_IMAGESAMPLE:
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
return false;
break;
default:
break;
}
// Check valid test type and readOp combination
switch (testType)
{
case TESTTYPE_OPTYPEIMAGE_MISMATCH:
// OPTYPEIMAGE_MISTMATCH does not test DEPTH formats
if (readOp == READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD || readOp == READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD)
return false;
break;
default:
break;
}
return true;
}
const char *getTestTypeName(TestType testType)
{
switch (testType)
{
case TESTTYPE_LOCAL_VARIABLES:
return "all_local_variables";
case TESTTYPE_PASS_IMAGE_TO_FUNCTION:
return "pass_image_to_function";
case TESTTYPE_PASS_SAMPLER_TO_FUNCTION:
return "pass_sampler_to_function";
case TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION:
return "pass_image_and_sampler_to_function";
case TESTTYPE_OPTYPEIMAGE_MISMATCH:
return "optypeimage_mismatch";
default:
DE_FATAL("Unknown test type");
return "";
}
}
const char *getReadOpName(ReadOp readOp)
{
switch (readOp)
{
case READOP_IMAGEREAD:
return "imageread";
case READOP_IMAGEFETCH:
return "imagefetch";
case READOP_IMAGESAMPLE:
return "imagesample";
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
return "imagesample_dref_implicit_lod";
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
return "imagesample_dref_explicit_lod";
default:
DE_FATAL("Unknown readop");
return "";
}
}
const char *getDescriptorName(DescriptorType descType)
{
switch (descType)
{
case DESCRIPTOR_TYPE_STORAGE_IMAGE:
return "storage_image";
case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
return "sampled_image";
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
return "combined_image_sampler";
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
return "combined_image_sampler_separate_variables";
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
return "combined_image_sampler_separate_descriptors";
default:
DE_FATAL("Unknown descriptor type");
return "";
}
}
const char *getDepthPropertyName(DepthProperty depthProperty)
{
switch (depthProperty)
{
case DEPTH_PROPERTY_NON_DEPTH:
return "non_depth";
case DEPTH_PROPERTY_DEPTH:
return "depth";
case DEPTH_PROPERTY_UNKNOWN:
return "unknown";
default:
DE_FATAL("Unknown depth property");
return "";
}
}
VkDescriptorType getVkDescriptorType(DescriptorType descType)
{
switch (descType)
{
case DESCRIPTOR_TYPE_STORAGE_IMAGE:
return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
default:
DE_FATAL("Unknown descriptor type");
return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
}
}
VkFormat getImageFormat(ReadOp readOp)
{
switch (readOp)
{
case READOP_IMAGEREAD:
case READOP_IMAGEFETCH:
case READOP_IMAGESAMPLE:
return VK_FORMAT_R32G32B32A32_SFLOAT;
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
return VK_FORMAT_D32_SFLOAT;
default:
DE_FATAL("Unknown readop");
return VK_FORMAT_UNDEFINED;
}
}
// Get variables that are declared in the read function, ie. not passed as parameters
std::string getFunctionDstVariableStr(ReadOp readOp, DescriptorType descType, TestType testType)
{
const bool passNdx = (testType == TESTTYPE_LOCAL_VARIABLES) || (testType == TESTTYPE_OPTYPEIMAGE_MISMATCH);
const bool passImg =
((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
const bool passSmp =
((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
std::string result = "";
switch (descType)
{
case DESCRIPTOR_TYPE_STORAGE_IMAGE:
{
switch (readOp)
{
case READOP_IMAGEREAD:
if (passNdx)
return " %func_img = OpLoad %Image %InputData\n";
break;
default:
DE_FATAL("Not possible");
break;
}
break;
}
case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
{
switch (readOp)
{
case READOP_IMAGEFETCH:
if (passNdx)
return " %func_img = OpLoad %Image %InputData\n";
if (passSmp && !passImg)
return " %func_tmp = OpLoad %Image %InputData\n"
" %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
" %func_img = OpImage %Image %func_smi\n";
if (passSmp && passImg)
return " %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
" %func_img = OpImage %Image %func_smi\n";
break;
case READOP_IMAGESAMPLE:
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
if (passNdx)
return " %func_img = OpLoad %Image %InputData\n"
" %func_smp = OpLoad %Sampler %SamplerData\n"
" %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
if (passImg && !passSmp)
return " %func_smp = OpLoad %Sampler %SamplerData\n"
" %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
if (passSmp && !passImg)
return " %func_img = OpLoad %Image %InputData\n"
" %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
if (passSmp && passImg)
return " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
break;
default:
DE_FATAL("Not possible");
}
break;
}
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
{
switch (readOp)
{
case READOP_IMAGEFETCH:
if (passNdx)
return " %func_smi = OpLoad %SampledImage %InputData\n"
" %func_img = OpImage %Image %func_smi\n";
break;
case READOP_IMAGESAMPLE:
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
if (passNdx)
return " %func_smi = OpLoad %SampledImage %InputData\n";
break;
default:
DE_FATAL("Not possible");
}
break;
}
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
{
switch (readOp)
{
case READOP_IMAGEFETCH:
if (passNdx)
return " %func_img = OpLoad %Image %InputData2\n";
if (passSmp && !passImg)
return " %func_tmp = OpLoad %Image %InputData2\n"
" %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
" %func_img = OpImage %Image %func_smi\n";
if (passSmp && passImg)
return " %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
" %func_img = OpImage %Image %func_smi\n";
break;
case READOP_IMAGESAMPLE:
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
if (passNdx)
return " %func_img = OpLoad %Image %InputData2\n"
" %func_smp = OpLoad %Sampler %SamplerData\n"
" %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
if (passImg && !passSmp)
return " %func_smp = OpLoad %Sampler %SamplerData\n"
" %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
if (passSmp && !passImg)
return " %func_img = OpLoad %Image %InputData2\n"
" %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
if (passSmp && passImg)
return " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
break;
default:
DE_FATAL("Not possible");
}
break;
}
default:
DE_FATAL("Unknown descriptor type");
}
return result;
}
// Get variables that are passed to the read function
std::string getFunctionSrcVariableStr(ReadOp readOp, DescriptorType descType, TestType testType)
{
const bool passImg =
((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
const bool passSmp =
((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
string result = "";
switch (descType)
{
case DESCRIPTOR_TYPE_STORAGE_IMAGE:
{
switch (readOp)
{
case READOP_IMAGEREAD:
if (passImg)
result += " %call_img = OpLoad %Image %InputData\n";
break;
default:
DE_FATAL("Not possible");
}
break;
}
case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
{
switch (readOp)
{
case READOP_IMAGEFETCH:
case READOP_IMAGESAMPLE:
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
if (passImg)
result += " %call_img = OpLoad %Image %InputData\n";
if (passSmp)
result += " %call_smp = OpLoad %Sampler %SamplerData\n";
break;
default:
DE_FATAL("Not possible");
}
break;
}
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
{
break;
}
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
{
switch (readOp)
{
case READOP_IMAGEFETCH:
case READOP_IMAGESAMPLE:
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
if (passImg)
result += " %call_img = OpLoad %Image %InputData2\n";
if (passSmp)
result += " %call_smp = OpLoad %Sampler %SamplerData\n";
break;
default:
DE_FATAL("Not possible");
}
break;
}
default:
DE_FATAL("Unknown descriptor type");
}
return result;
}
// Get parameter types for OpTypeFunction
std::string getFunctionParamTypeStr(TestType testType)
{
const bool passImg =
((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
const bool passSmp =
((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
string result = "";
if (passImg)
result += " %Image";
if (passSmp)
result += " %Sampler";
return result;
}
// Get argument names for OpFunctionCall
std::string getFunctionSrcParamStr(TestType testType)
{
const bool passImg =
((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
const bool passSmp =
((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
string result = "";
if (passImg)
result += " %call_img";
if (passSmp)
result += " %call_smp";
return result;
}
// Get OpFunctionParameters
std::string getFunctionDstParamStr(ReadOp readOp, TestType testType)
{
const bool passImg =
((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
const bool passSmp =
((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
string result = "";
switch (readOp)
{
case READOP_IMAGESAMPLE:
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
if (passImg)
result += " %func_img = OpFunctionParameter %Image\n";
if (passSmp)
result += " %func_smp = OpFunctionParameter %Sampler\n";
break;
default:
if (passImg && !passSmp)
result += " %func_img = OpFunctionParameter %Image\n";
if (passSmp && !passImg)
result += " %func_smp = OpFunctionParameter %Sampler\n";
if (passImg && passSmp)
result += " %func_tmp = OpFunctionParameter %Image\n"
" %func_smp = OpFunctionParameter %Sampler\n";
break;
}
return result;
}
struct FormatDataForShaders
{
vk::VkFormat m_format;
std::string m_name;
std::string m_spirvMismatchFormat;
std::string m_spirvType;
std::string m_spirvVectorType;
};
static const FormatDataForShaders optypeimageFormatMismatchSpirvData[] = {
{vk::VK_FORMAT_R8G8B8A8_UNORM, "rgba8", "Rgba16f", "%f32", "%v4f32"},
{vk::VK_FORMAT_R8G8B8A8_SNORM, "rgba8snorm", "Rgba16f", "%f32", "%v4f32"},
{vk::VK_FORMAT_R8G8B8A8_UINT, "rgba8ui", "Rgba16ui", "%u32", "%v4u32"},
{vk::VK_FORMAT_R8G8B8A8_SINT, "rgba8i", "Rgba16i", "%i32", "%v4i32"},
{vk::VK_FORMAT_R16G16B16A16_UINT, "rgba16ui", "Rgba32ui", "%u32", "%v4u32"},
{vk::VK_FORMAT_R16G16B16A16_SINT, "rgba16i", "Rgba32i", "%i32", "%v4i32"},
{vk::VK_FORMAT_R16G16B16A16_SFLOAT, "rgba16f", "Rgba32f", "%f32", "%v4f32"},
{vk::VK_FORMAT_R32_UINT, "r32ui", "Rgba32ui", "%u32", "%v4u32"},
{vk::VK_FORMAT_R32_SINT, "r32i", "Rgba32i", "%i32", "%v4i32"},
{vk::VK_FORMAT_R32G32B32A32_UINT, "rgba32ui", "Rgba8ui", "%u32", "%v4u32"},
{vk::VK_FORMAT_R32G32B32A32_SINT, "rgba32i", "Rgba8i", "%i32", "%v4i32"},
{vk::VK_FORMAT_R32G32B32A32_SFLOAT, "rgba32f", "Rgba8", "%f32", "%v4f32"},
};
static const uint32_t optypeimageFormatMismatchFormatCount = DE_LENGTH_OF_ARRAY(optypeimageFormatMismatchSpirvData);
// Get read operation
std::string getImageReadOpStr(ReadOp readOp, const FormatDataForShaders &formatData, bool useNontemporal = false)
{
std::string imageOperand = useNontemporal ? " Nontemporal" : "";
switch (readOp)
{
case READOP_IMAGEREAD:
return "OpImageRead " + formatData.m_spirvVectorType + " %func_img %coord" + imageOperand;
case READOP_IMAGEFETCH:
return "OpImageFetch " + formatData.m_spirvVectorType + " %func_img %coord" + imageOperand;
case READOP_IMAGESAMPLE:
if (useNontemporal)
return "OpImageSampleExplicitLod " + formatData.m_spirvVectorType +
" %func_smi %normalcoordf Lod|Nontemporal %c_f32_0";
return "OpImageSampleExplicitLod " + formatData.m_spirvVectorType + " %func_smi %normalcoordf Lod %c_f32_0";
case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
return "OpImageSampleDrefImplicitLod %f32 %func_smi %normalcoordf %c_f32_0_5 Bias %c_f32_0";
case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
return "OpImageSampleDrefExplicitLod %f32 %func_smi %normalcoordf %c_f32_0_5 Lod %c_f32_0";
default:
DE_FATAL("Unknown readop");
return "";
}
}
bool isImageSampleDrefReadOp(ReadOp readOp)
{
return (readOp == READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD) || (readOp == READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD);
}
// Get types and pointers for input images and samplers
std::string getImageSamplerTypeStr(DescriptorType descType, ReadOp readOp, uint32_t depthProperty, TestType testType,
const FormatDataForShaders &formatData)
{
const string imageFormat = (testType == TESTTYPE_OPTYPEIMAGE_MISMATCH) ? formatData.m_spirvMismatchFormat :
isImageSampleDrefReadOp(readOp) ? "R32f" :
"Rgba32f";
switch (descType)
{
case DESCRIPTOR_TYPE_STORAGE_IMAGE:
return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) +
" 0 0 2 " + imageFormat +
"\n"
" %ImagePtr = OpTypePointer UniformConstant %Image\n"
" %InputData = OpVariable %ImagePtr UniformConstant\n";
case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) +
" 0 0 1 " + imageFormat +
"\n"
" %ImagePtr = OpTypePointer UniformConstant %Image\n"
" %InputData = OpVariable %ImagePtr UniformConstant\n"
" %Sampler = OpTypeSampler\n"
" %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
" %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
" %SampledImage = OpTypeSampledImage %Image\n";
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) +
" 0 0 1 " + imageFormat +
"\n"
" %SampledImage = OpTypeSampledImage %Image\n"
" %SamplerPtr = OpTypePointer UniformConstant %SampledImage\n"
" %InputData = OpVariable %SamplerPtr UniformConstant\n";
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) +
" 0 0 1 " + imageFormat +
"\n"
" %ImagePtr = OpTypePointer UniformConstant %Image\n"
" %InputData = OpVariable %ImagePtr UniformConstant\n"
" %Sampler = OpTypeSampler\n"
" %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
" %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
" %SampledImage = OpTypeSampledImage %Image\n";
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) +
" 0 0 1 " + imageFormat +
"\n"
" %ImagePtr = OpTypePointer UniformConstant %Image\n"
" %InputData = OpVariable %ImagePtr UniformConstant\n"
" %InputData2 = OpVariable %ImagePtr UniformConstant\n"
" %Sampler = OpTypeSampler\n"
" %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
" %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
" %SamplerData2 = OpVariable %SamplerPtr UniformConstant\n"
" %SampledImage = OpTypeSampledImage %Image\n";
default:
DE_FATAL("Unknown descriptor type");
return "";
}
}
std::string getInterfaceList(DescriptorType descType)
{
std::string list = " %InputData %OutputData";
switch (descType)
{
case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
list += " %SamplerData";
break;
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
list += " %SamplerData %InputData2 %SamplerData2";
break;
default:
break;
}
return list;
}
std::string getSamplerDecoration(DescriptorType descType)
{
switch (descType)
{
// Separate image and sampler
case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
return " OpDecorate %SamplerData DescriptorSet 0\n"
" OpDecorate %SamplerData Binding 1\n";
// Combined image sampler with separate variables
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
return " OpDecorate %SamplerData DescriptorSet 0\n"
" OpDecorate %SamplerData Binding 0\n";
// Two combined image samplers with separate variables
case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
return " OpDecorate %SamplerData DescriptorSet 0\n"
" OpDecorate %SamplerData Binding 0\n"
" OpDecorate %InputData2 DescriptorSet 0\n"
" OpDecorate %InputData2 Binding 1\n"
" OpDecorate %SamplerData2 DescriptorSet 0\n"
" OpDecorate %SamplerData2 Binding 1\n";
default:
return "";
}
}
// no-operation verify functon to ignore test results (optypeimage_mismatch)
bool nopVerifyFunction(const std::vector<Resource> &, const std::vector<AllocationSp> &, const std::vector<Resource> &,
tcu::TestLog &)
{
return true;
}
void addComputeImageSamplerTest(tcu::TestCaseGroup *group)
{
tcu::TestContext &testCtx = group->getTestContext();
de::Random rnd(deStringHash(group->getName()));
const uint32_t numDataPoints = 64;
RGBA defaultColors[4];
vector<tcu::Vec4> inputData;
inputData.reserve(numDataPoints);
for (uint32_t numIdx = 0; numIdx < numDataPoints; ++numIdx)
inputData.push_back(tcu::randomVec4(rnd));
struct SpirvData
{
SpirvVersion version;
std::string postfix;
};
const std::vector<SpirvData> spirvDataVect{
{SPIRV_VERSION_1_0, ""},
{SPIRV_VERSION_1_6, "_nontemporal"},
};
for (uint32_t opNdx = 0u; opNdx <= READOP_IMAGESAMPLE; opNdx++)
{
de::MovePtr<tcu::TestCaseGroup> readOpGroup(new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx)));
for (uint32_t descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++)
{
de::MovePtr<tcu::TestCaseGroup> descGroup(
new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx)));
for (uint32_t testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++)
{
if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx))
continue;
uint32_t numFormats = 1;
if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
numFormats = optypeimageFormatMismatchFormatCount;
for (uint32_t formatIndex = 0; formatIndex < numFormats; formatIndex++)
{
const FormatDataForShaders &formatData = optypeimageFormatMismatchSpirvData[formatIndex];
const std::string functionParamTypes = getFunctionParamTypeStr((TestType)testNdx);
const std::string functionSrcVariables =
getFunctionSrcVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
const std::string functionDstVariables =
getFunctionDstVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
const std::string functionSrcParams = getFunctionSrcParamStr((TestType)testNdx);
const std::string functionDstParams = getFunctionDstParamStr((ReadOp)opNdx, (TestType)testNdx);
getDefaultColors(defaultColors);
ComputeShaderSpec spec;
spec.numWorkGroups = IVec3(numDataPoints, 1, 1);
spec.inputs.push_back(
Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
// Separate sampler for sampled images
if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_SAMPLED_IMAGE)
{
vector<tcu::Vec4> unusedData;
spec.inputs.push_back(Resource(BufferSp(new Vec4Buffer(unusedData))));
spec.inputs[1].setDescriptorType(VK_DESCRIPTOR_TYPE_SAMPLER);
}
// Second combined image sampler with different image data
if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
{
for (size_t i = 0; i < inputData.size(); i++)
inputData[i] = tcu::Vec4(1.0f) - inputData[i];
spec.inputs.push_back(BufferSp(new Vec4Buffer(inputData)));
spec.inputs[1].setDescriptorType(getVkDescriptorType((DescriptorType)descNdx));
}
// Shader is expected to pass the input image data to the output buffer
spec.outputs.push_back(BufferSp(new Vec4Buffer(inputData)));
const std::string samplerDecoration = getSamplerDecoration((DescriptorType)descNdx);
for (auto spirvData : spirvDataVect)
{
spec.spirvVersion = spirvData.version;
bool useSpirV16(spirvData.version == SPIRV_VERSION_1_6);
std::string interfaceList("");
std::string outputDecoration("BufferBlock");
std::string outputType("Uniform");
std::string imageReadOp(getImageReadOpStr((ReadOp)opNdx, formatData, useSpirV16));
// adjust shader code to spv16
if (useSpirV16)
{
interfaceList = getInterfaceList((DescriptorType)descNdx);
outputDecoration = "Block";
outputType = "StorageBuffer";
}
string testname = getTestTypeName((TestType)testNdx);
if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
{
// If testing for mismatched optypeimage, ignore the
// result (we're only interested to see if we crash)
spec.verifyIO = nopVerifyFunction;
spec.inputFormat = formatData.m_format;
testname = testname + string("_") + formatData.m_name;
}
testname += spirvData.postfix;
de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, testname.c_str()));
de::MovePtr<tcu::TestCaseGroup> depthGroup(new tcu::TestCaseGroup(testCtx, "depth_property"));
for (uint32_t propertyNdx = 0u; propertyNdx < DEPTH_PROPERTY_LAST; propertyNdx++)
{
const std::string imageSamplerTypes =
getImageSamplerTypeStr((DescriptorType)descNdx, (ReadOp)opNdx,
(DepthProperty)propertyNdx, (TestType)testNdx, formatData);
const string shaderSource =
" OpCapability Shader\n"
" %1 = OpExtInstImport \"GLSL.std.450\"\n"
" OpMemoryModel Logical GLSL450\n"
" OpEntryPoint GLCompute %main \"main\" %id" +
interfaceList +
"\n"
" OpExecutionMode %main LocalSize 1 1 1\n"
" OpSource GLSL 430\n"
" OpDecorate %id BuiltIn GlobalInvocationId\n"
" OpDecorate %_arr_v4type_u32_64 ArrayStride 16\n"
" OpMemberDecorate %Output 0 Offset 0\n"
" OpDecorate %Output " +
outputDecoration +
"\n"
" OpDecorate %InputData DescriptorSet 0\n"
" OpDecorate %InputData Binding 0\n"
+ samplerDecoration +
" OpDecorate %OutputData DescriptorSet 0\n"
" OpDecorate %OutputData Binding " +
de::toString(spec.inputs.size()) +
"\n"
" %void = OpTypeVoid\n"
" %3 = OpTypeFunction %void\n"
" %u32 = OpTypeInt 32 0\n"
" %i32 = OpTypeInt 32 1\n"
" %f32 = OpTypeFloat 32\n"
" %_ptr_Function_uint = OpTypePointer Function %u32\n"
" %v3u32 = OpTypeVector %u32 3\n"
" %_ptr_Input_v3u32 = OpTypePointer Input %v3u32\n"
" %id = OpVariable %_ptr_Input_v3u32 Input\n"
" %c_f32_0 = OpConstant %f32 0.0\n"
" %c_u32_0 = OpConstant %u32 0\n"
" %c_i32_0 = OpConstant %i32 0\n"
" %_ptr_Input_uint = OpTypePointer Input %u32\n"
" %v2u32 = OpTypeVector %u32 2\n"
" %v2f32 = OpTypeVector %f32 2\n"
" %v4f32 = OpTypeVector %f32 4\n"
" %v4u32 = OpTypeVector %u32 4\n"
" %v4i32 = OpTypeVector %i32 4\n"
" %uint_128 = OpConstant %u32 128\n"
" %c_u32_64 = OpConstant %u32 64\n"
" %c_u32_8 = OpConstant %u32 8\n"
" %c_f32_8 = OpConstant %f32 8.0\n"
" %c_v2f32_8_8 = OpConstantComposite %v2f32 %c_f32_8 %c_f32_8\n"
" %_arr_v4type_u32_64 = OpTypeArray " +
formatData.m_spirvVectorType +
" %c_u32_64\n"
"%_ptr_Uniform_v4type = OpTypePointer " +
outputType + " " + formatData.m_spirvVectorType +
"\n"
" %Output = OpTypeStruct %_arr_v4type_u32_64\n"
"%_ptr_Uniform_Output = OpTypePointer " +
outputType +
" %Output\n"
" %OutputData = OpVariable %_ptr_Uniform_Output " +
outputType + "\n"
+ imageSamplerTypes +
" %read_func_type = OpTypeFunction %void %u32" + functionParamTypes +
"\n"
" %read_func = OpFunction %void None %read_func_type\n"
" %func_ndx = OpFunctionParameter %u32\n"
+ functionDstParams +
" %funcentry = OpLabel\n"
" %row = OpUMod %u32 %func_ndx %c_u32_8\n"
" %col = OpUDiv %u32 %func_ndx %c_u32_8\n"
" %coord = OpCompositeConstruct %v2u32 %row %col\n"
" %coordf = OpConvertUToF %v2f32 %coord\n"
" %normalcoordf = OpFDiv %v2f32 %coordf %c_v2f32_8_8\n"
+ functionDstVariables +
" %color = " + imageReadOp +
"\n"
" %36 = OpAccessChain %_ptr_Uniform_v4type %OutputData %c_u32_0 "
"%func_ndx\n"
" OpStore %36 %color\n"
" OpReturn\n"
" OpFunctionEnd\n"
" %main = OpFunction %void None %3\n"
" %5 = OpLabel\n"
" %i = OpVariable %_ptr_Function_uint Function\n"
" %14 = OpAccessChain %_ptr_Input_uint %id %c_u32_0\n"
" %15 = OpLoad %u32 %14\n"
" OpStore %i %15\n"
" %index = OpLoad %u32 %14\n"
+ functionSrcVariables +
" %res = OpFunctionCall %void %read_func %index" + functionSrcParams +
"\n"
" OpReturn\n"
" OpFunctionEnd\n";
spec.assembly = shaderSource;
depthGroup->addChild(new SpvAsmComputeShaderCase(
testCtx, getDepthPropertyName((DepthProperty)propertyNdx), spec));
}
typeGroup->addChild(depthGroup.release());
descGroup->addChild(typeGroup.release());
}
}
}
readOpGroup->addChild(descGroup.release());
}
group->addChild(readOpGroup.release());
}
}
map<string, string> generateGraphicsImageSamplerSource(ReadOp readOp, DescriptorType descriptorType, TestType testType,
DepthProperty depthProperty, uint32_t outputBinding,
uint32_t formatIndex)
{
map<string, string> source;
const FormatDataForShaders &formatData = optypeimageFormatMismatchSpirvData[formatIndex];
const std::string imageReadOp = getImageReadOpStr(readOp, formatData);
const std::string imageSamplerTypes =
getImageSamplerTypeStr(descriptorType, readOp, depthProperty, testType, formatData);
const std::string functionParamTypes = getFunctionParamTypeStr(testType);
const std::string functionSrcVariables = getFunctionSrcVariableStr(readOp, descriptorType, testType);
const std::string functionDstVariables = getFunctionDstVariableStr(readOp, descriptorType, testType);
const std::string functionSrcParams = getFunctionSrcParamStr(testType);
const std::string functionDstParams = getFunctionDstParamStr(readOp, testType);
const std::string samplerDecoration = getSamplerDecoration(descriptorType);
const std::string outputUniformPtr =
isImageSampleDrefReadOp(readOp) ? "%_ptr_Uniform_type" : "%_ptr_Uniform_v4type";
const std::string outputArrayStruct = isImageSampleDrefReadOp(readOp) ? "%_arr_type_u32_64" : "%_arr_v4type_u32_64";
source["pre_main"] = " %c_u32_64 = OpConstant %u32 64\n"
" %c_i32_64 = OpConstant %i32 64\n"
" %c_i32_8 = OpConstant %i32 8\n"
" %c_v2f32_8_8 = OpConstantComposite %v2f32 %c_f32_8 %c_f32_8\n"
" %_arr_type_u32_64 = OpTypeArray " +
formatData.m_spirvType +
" %c_u32_64\n"
" %_arr_v4type_u32_64 = OpTypeArray " +
formatData.m_spirvVectorType +
" %c_u32_64\n"
" %_ptr_Uniform_type = OpTypePointer Uniform " +
formatData.m_spirvType +
"\n"
"%_ptr_Uniform_v4type = OpTypePointer Uniform " +
formatData.m_spirvVectorType +
"\n"
" %Output = OpTypeStruct " +
outputArrayStruct +
"\n"
"%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
" %OutputData = OpVariable %_ptr_Uniform_Output Uniform\n"
+ imageSamplerTypes +
" %read_func_type = OpTypeFunction %void %i32" + functionParamTypes + "\n";
source["decoration"] = " OpDecorate %_arr_type_u32_64 ArrayStride 4\n"
" OpDecorate %_arr_v4type_u32_64 ArrayStride 16\n"
" OpMemberDecorate %Output 0 Offset 0\n"
" OpDecorate %Output BufferBlock\n"
" OpDecorate %InputData DescriptorSet 0\n"
" OpDecorate %InputData Binding 0\n"
+ samplerDecoration +
"OpDecorate %OutputData DescriptorSet 0\n"
"OpDecorate %OutputData Binding " +
de::toString(outputBinding) + "\n";
source["testfun"] = " %read_func = OpFunction %void None %read_func_type\n"
" %func_ndx = OpFunctionParameter %i32\n"
+ functionDstParams +
" %funcentry = OpLabel\n"
" %row = OpSRem %i32 %func_ndx %c_i32_8\n"
" %col = OpSDiv %i32 %func_ndx %c_i32_8\n"
" %coord = OpCompositeConstruct %v2i32 %row %col\n"
" %coordf = OpConvertSToF %v2f32 %coord\n"
" %normalcoordf = OpFDiv %v2f32 %coordf %c_v2f32_8_8\n"
+ functionDstVariables +
" %color = " + imageReadOp +
"\n"
" %36 = OpAccessChain " +
outputUniformPtr +
" %OutputData %c_i32_0 %func_ndx\n"
" OpStore %36 %color\n"
" OpReturn\n"
" OpFunctionEnd\n"
" %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
" %param = OpFunctionParameter %v4f32\n"
" %entry = OpLabel\n"
" %i = OpVariable %fp_i32 Function\n"
" OpStore %i %c_i32_0\n"
" OpBranch %loop\n"
" %loop = OpLabel\n"
" %15 = OpLoad %i32 %i\n"
" %lt = OpSLessThan %bool %15 %c_i32_64\n"
" OpLoopMerge %merge %inc None\n"
" OpBranchConditional %lt %write %merge\n"
" %write = OpLabel\n"
" %index = OpLoad %i32 %i\n"
+ functionSrcVariables +
" %res = OpFunctionCall %void %read_func %index" + functionSrcParams +
"\n"
" OpBranch %inc\n"
" %inc = OpLabel\n"
" %37 = OpLoad %i32 %i\n"
" %39 = OpIAdd %i32 %37 %c_i32_1\n"
" OpStore %i %39\n"
" OpBranch %loop\n"
" %merge = OpLabel\n"
" OpReturnValue %param\n"
" OpFunctionEnd\n";
return source;
}
bool verifyDepthCompareResult(const std::vector<Resource> &originalFloats,
const std::vector<AllocationSp> &outputAllocs,
const std::vector<Resource> &expectedOutputs, tcu::TestLog &)
{
DE_UNREF(originalFloats);
if (outputAllocs.size() != expectedOutputs.size())
return false;
vector<uint8_t> expectedBytes;
expectedOutputs[0].getBytes(expectedBytes);
const float *returnedAsFloat = static_cast<const float *>(outputAllocs[0]->getHostPtr());
const float *expectedAsFloat = reinterpret_cast<const float *>(&expectedBytes.front());
for (uint32_t elementNdx = 0; elementNdx < static_cast<uint32_t>(expectedBytes.size() / sizeof(float));
++elementNdx)
{
const float input = expectedAsFloat[elementNdx];
const float result = returnedAsFloat[elementNdx];
// VK_COMPARE_OP_LESS: D = 1.0 if D < Dref, otherwise D = 0.0
if ((input < 0.5f && result != 0.0f) || (input >= 0.5f && result != 1.0f))
return false;
}
return true;
}
void addGraphicsImageSamplerTest(tcu::TestCaseGroup *group)
{
tcu::TestContext &testCtx = group->getTestContext();
de::Random rnd(deStringHash(group->getName()));
const uint32_t numDataPoints = 64;
RGBA defaultColors[4];
SpecConstants noSpecConstants;
PushConstants noPushConstants;
GraphicsInterfaces noInterfaces;
std::vector<std::string> noExtensions;
VulkanFeatures vulkanFeatures = VulkanFeatures();
vector<tcu::Vec4> inputDataBase(numDataPoints);
for (uint32_t numIdx = 0; numIdx < numDataPoints; ++numIdx)
inputDataBase[numIdx] = tcu::randomVec4(rnd);
// Depth only has 1 component
vector<tcu::Vec4> inputDataBaseDepth = inputDataBase;
inputDataBaseDepth.resize(numDataPoints / 4);
for (uint32_t opNdx = 0u; opNdx < READOP_LAST; opNdx++)
{
de::MovePtr<tcu::TestCaseGroup> readOpGroup(new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx)));
const VkFormat imageFormat = getImageFormat((ReadOp)opNdx);
const bool hasDepthComponent = tcu::hasDepthComponent(vk::mapVkFormat(imageFormat).order);
for (uint32_t descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++)
{
de::MovePtr<tcu::TestCaseGroup> descGroup(
new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx)));
for (uint32_t testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++)
{
if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx))
continue;
uint32_t formatCount = 1;
if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
formatCount = optypeimageFormatMismatchFormatCount;
// this group is only used for optypeimage_mismatch case
de::MovePtr<tcu::TestCaseGroup> testtypeGroup(
new tcu::TestCaseGroup(testCtx, getTestTypeName((TestType)testNdx)));
for (uint32_t formatIndex = 0; formatIndex < formatCount; formatIndex++)
{
const FormatDataForShaders &formatData = optypeimageFormatMismatchSpirvData[formatIndex];
// optypeimage_mismatch uses an additional level of test hierarchy
const char *groupname = (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH) ?
formatData.m_name.c_str() :
getTestTypeName((TestType)testNdx);
de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, groupname));
vector<Vec4> &inputData = hasDepthComponent && testNdx != TESTTYPE_OPTYPEIMAGE_MISMATCH ?
inputDataBaseDepth :
inputDataBase;
GraphicsResources resources;
resources.inputs.push_back(
Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
// Separate sampler for sampled images
if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_SAMPLED_IMAGE)
{
vector<tcu::Vec4> unusedData;
resources.inputs.push_back(
Resource(BufferSp(new Vec4Buffer(unusedData)), VK_DESCRIPTOR_TYPE_SAMPLER));
}
// Second combined image sampler with different image data
if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
{
for (size_t i = 0; i < inputData.size(); i++)
inputData[i] = tcu::Vec4(1.0f) - inputData[i];
resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)),
getVkDescriptorType((DescriptorType)descNdx)));
}
// Shader is expected to pass the input image data to output buffer
resources.outputs.push_back(
Resource(BufferSp(new Vec4Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
getDefaultColors(defaultColors);
// If testing for mismatched optypeimage, ignore the rendered
// result (we're only interested to see if we crash)
if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
{
resources.verifyIO = nopVerifyFunction;
resources.inputFormat = formatData.m_format;
}
else if (hasDepthComponent)
{
resources.verifyIO = verifyDepthCompareResult;
resources.inputFormat = getImageFormat((ReadOp)opNdx);
}
de::MovePtr<tcu::TestCaseGroup> depthGroup(new tcu::TestCaseGroup(testCtx, "depth_property"));
for (uint32_t propertyNdx = 0u; propertyNdx < DEPTH_PROPERTY_LAST; propertyNdx++)
{
de::MovePtr<tcu::TestCaseGroup> depthPropertyGroup(
new tcu::TestCaseGroup(testCtx, getDepthPropertyName((DepthProperty)propertyNdx)));
const map<string, string> fragments = generateGraphicsImageSamplerSource(
(ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx, (DepthProperty)propertyNdx,
(uint32_t)resources.inputs.size(), formatIndex);
// READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD and READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD can only be present in fragment/compute
if (opNdx <= READOP_IMAGESAMPLE)
{
vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = false;
createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, "shader_vert", defaultColors, defaultColors,
fragments, noSpecConstants, noPushConstants, resources, noInterfaces,
noExtensions, vulkanFeatures, depthPropertyGroup.get());
createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "shader_tessc", defaultColors,
defaultColors, fragments, noSpecConstants, noPushConstants, resources,
noInterfaces, noExtensions, vulkanFeatures, depthPropertyGroup.get());
createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "shader_tesse",
defaultColors, defaultColors, fragments, noSpecConstants,
noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures,
depthPropertyGroup.get());
createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, "shader_geom", defaultColors,
defaultColors, fragments, noSpecConstants, noPushConstants, resources,
noInterfaces, noExtensions, vulkanFeatures, depthPropertyGroup.get());
}
vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = false;
vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = true;
createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, "shader_frag", defaultColors, defaultColors,
fragments, noSpecConstants, noPushConstants, resources, noInterfaces,
noExtensions, vulkanFeatures, depthPropertyGroup.get());
depthGroup->addChild(depthPropertyGroup.release());
}
typeGroup->addChild(depthGroup.release());
if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
testtypeGroup->addChild(typeGroup.release());
else
descGroup->addChild(typeGroup.release());
}
if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
descGroup->addChild(testtypeGroup.release());
}
readOpGroup->addChild(descGroup.release());
}
group->addChild(readOpGroup.release());
}
}
} // namespace
tcu::TestCaseGroup *createImageSamplerComputeGroup(tcu::TestContext &testCtx)
{
// Compute tests for combining images and samplers.
de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "image_sampler"));
addComputeImageSamplerTest(group.get());
return group.release();
}
tcu::TestCaseGroup *createImageSamplerGraphicsGroup(tcu::TestContext &testCtx)
{
// Graphics tests for combining images and samplers.
de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "image_sampler"));
addGraphicsImageSamplerTest(group.get());
return group.release();
}
} // namespace SpirVAssembly
} // namespace vkt