| /*------------------------------------------------------------------------- |
| * 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" |
| |
| 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; |
| } |
| |
| 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 = ""; |
| |
| if (readOp == READOP_IMAGESAMPLE) |
| { |
| if (passImg) |
| result += " %func_img = OpFunctionParameter %Image\n"; |
| |
| if (passSmp) |
| result += " %func_smp = OpFunctionParameter %Sampler\n"; |
| } |
| else |
| { |
| 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"; |
| } |
| |
| return result; |
| } |
| |
| // Get read operation |
| std::string getImageReadOpStr (ReadOp readOp) |
| { |
| switch (readOp) |
| { |
| case READOP_IMAGEREAD: |
| return "OpImageRead %v4f32 %func_img %coord"; |
| |
| case READOP_IMAGEFETCH: |
| return "OpImageFetch %v4f32 %func_img %coord"; |
| |
| case READOP_IMAGESAMPLE: |
| return "OpImageSampleExplicitLod %v4f32 %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); |
| } |
| |
| static const VkFormat optypeimageFormatMismatchVkFormat[] = |
| { |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R8G8B8A8_SNORM, |
| VK_FORMAT_R8G8B8A8_UINT, |
| VK_FORMAT_R8G8B8A8_SINT, |
| VK_FORMAT_R16G16B16A16_UINT, |
| VK_FORMAT_R16G16B16A16_SINT, |
| VK_FORMAT_R16G16B16A16_SFLOAT, |
| VK_FORMAT_R32_UINT, |
| VK_FORMAT_R32_SINT, |
| VK_FORMAT_R32G32B32A32_UINT, |
| VK_FORMAT_R32G32B32A32_SINT, |
| VK_FORMAT_R32G32B32A32_SFLOAT |
| }; |
| |
| static const size_t optypeimageFormatMismatchFormatCount = sizeof(optypeimageFormatMismatchVkFormat) / sizeof(VkFormat); |
| |
| static const char *optypeimageFormatMismatchSpirvFormat[] = |
| { |
| "Rgba8", |
| "Rgba8Snorm", |
| "Rgba8ui", |
| "Rgba8i", |
| "Rgba16ui", |
| "Rgba16i", |
| "Rgba16f", |
| "R32ui", |
| "R32i", |
| "Rgba32ui", |
| "Rgba32i", |
| "Rgba32f" |
| }; |
| |
| static const char *optypeimageFormatMismatchCase[] = |
| { |
| "rgba8", |
| "rgba8snorm", |
| "rgba8ui", |
| "rgba8i", |
| "rgba16ui", |
| "rgba16i", |
| "rgba16f", |
| "r32ui", |
| "r32i", |
| "rgba32ui", |
| "rgba32i", |
| "rgba32f" |
| }; |
| |
| // Get types and pointers for input images and samplers |
| std::string getImageSamplerTypeStr (DescriptorType descType, ReadOp readOp, deUint32 depthProperty, TestType testType, int formatIndex) |
| { |
| const string imageFormat = (testType == TESTTYPE_OPTYPEIMAGE_MISMATCH) ? optypeimageFormatMismatchSpirvFormat[formatIndex] : |
| isImageSampleDrefReadOp(readOp) ? "R32f" : "Rgba32f"; |
| |
| switch (descType) |
| { |
| case DESCRIPTOR_TYPE_STORAGE_IMAGE: |
| return " %Image = OpTypeImage %f32 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 %f32 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 %f32 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 %f32 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 %f32 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 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 deUint32 numDataPoints = 64; |
| RGBA defaultColors[4]; |
| vector<tcu::Vec4> inputData; |
| |
| inputData.reserve(numDataPoints); |
| |
| for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx) |
| inputData.push_back(tcu::Vec4(rnd.getFloat(), rnd.getFloat(), rnd.getFloat(), rnd.getFloat())); |
| |
| for (deUint32 opNdx = 0u; opNdx <= READOP_IMAGESAMPLE; opNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> readOpGroup (new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx), "")); |
| |
| for (deUint32 descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx), "")); |
| |
| for (deUint32 testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++) |
| { |
| if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx)) |
| continue; |
| |
| deUint32 numFormats = 1; |
| if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH) |
| numFormats = optypeimageFormatMismatchFormatCount; |
| |
| for (deUint32 formatIndex = 0; formatIndex < numFormats; formatIndex++) |
| { |
| |
| const std::string imageReadOp = getImageReadOpStr((ReadOp)opNdx); |
| |
| const std::string imageSamplerTypes = getImageSamplerTypeStr((DescriptorType)descNdx, (ReadOp)opNdx, DEPTH_PROPERTY_NON_DEPTH, (TestType)testNdx, 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> dummyData; |
| spec.inputs.push_back(Resource(BufferSp(new Vec4Buffer(dummyData)))); |
| 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); |
| |
| const string shaderSource = |
| " OpCapability Shader\n" |
| " %1 = OpExtInstImport \"GLSL.std.450\"\n" |
| " OpMemoryModel Logical GLSL450\n" |
| " OpEntryPoint GLCompute %main \"main\" %id\n" |
| " OpExecutionMode %main LocalSize 1 1 1\n" |
| " OpSource GLSL 430\n" |
| " OpDecorate %id BuiltIn GlobalInvocationId\n" |
| " OpDecorate %_arr_v4f_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(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" |
| " %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_v4f_u32_64 = OpTypeArray %v4f32 %c_u32_64\n" |
| " %_ptr_Uniform_v4f = OpTypePointer Uniform %v4f32\n" |
| " %Output = OpTypeStruct %_arr_v4f_u32_64\n" |
| "%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n" |
| " %OutputData = OpVariable %_ptr_Uniform_Output Uniform\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_v4f %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; |
| |
| // If testing for mismatched optypeimage, ignore the |
| // result (we're only interested to see if we crash) |
| if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH) |
| spec.verifyIO = nopVerifyFunction; |
| |
| string testname = getTestTypeName((TestType)testNdx); |
| |
| if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH) |
| testname = testname + string("_") + string(optypeimageFormatMismatchCase[formatIndex]); |
| |
| descGroup->addChild(new SpvAsmComputeShaderCase(testCtx, testname.c_str(), "", spec)); |
| } |
| } |
| readOpGroup->addChild(descGroup.release()); |
| } |
| group->addChild(readOpGroup.release()); |
| } |
| } |
| |
| map<string, string> generateGraphicsImageSamplerSource (ReadOp readOp, DescriptorType descriptorType, TestType testType, DepthProperty depthProperty, deUint32 outputBinding, deUint32 formatIndex) |
| { |
| map<string, string> source; |
| |
| const std::string imageReadOp = getImageReadOpStr(readOp); |
| const std::string imageSamplerTypes = getImageSamplerTypeStr(descriptorType, readOp, depthProperty, testType, formatIndex); |
| 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_f32" : "%_ptr_Uniform_v4f32"; |
| const std::string outputArrayStruct = isImageSampleDrefReadOp(readOp) ? "%_arr_f32_u32_64" : "%_arr_v4f32_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_f32_u32_64 = OpTypeArray %f32 %c_u32_64\n" |
| " %_arr_v4f32_u32_64 = OpTypeArray %v4f32 %c_u32_64\n" |
| " %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n" |
| " %_ptr_Uniform_v4f32 = OpTypePointer Uniform %v4f32\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_f32_u32_64 ArrayStride 4\n" |
| " OpDecorate %_arr_v4f32_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; |
| } |
| |
| void addGraphicsImageSamplerTest (tcu::TestCaseGroup* group) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| de::Random rnd (deStringHash(group->getName())); |
| const deUint32 numDataPoints = 64; |
| RGBA defaultColors[4]; |
| |
| SpecConstants noSpecConstants; |
| PushConstants noPushConstants; |
| GraphicsInterfaces noInterfaces; |
| std::vector<std::string> noExtensions; |
| VulkanFeatures vulkanFeatures = VulkanFeatures(); |
| |
| vector<tcu::Vec4> inputData(numDataPoints); |
| for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx) |
| inputData[numIdx] = tcu::Vec4(rnd.getFloat(), rnd.getFloat(), rnd.getFloat(), rnd.getFloat()); |
| |
| for (deUint32 opNdx = 0u; opNdx <= READOP_IMAGESAMPLE; opNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> readOpGroup (new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx), "")); |
| |
| for (deUint32 descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx), "")); |
| |
| for (deUint32 testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++) |
| { |
| if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx)) |
| continue; |
| |
| deUint32 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 (deUint32 formatIndex = 0; formatIndex < formatCount; formatIndex++) |
| { |
| // optypeimage_mismatch uses an additional level of test hierarchy |
| const char *groupname = testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH ? optypeimageFormatMismatchCase[formatIndex] : getTestTypeName((TestType)testNdx); |
| de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, groupname, "")); |
| |
| 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> dummyData; |
| resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(dummyData)), 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); |
| |
| const map<string, string> fragments = generateGraphicsImageSamplerSource((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx, DEPTH_PROPERTY_NON_DEPTH, (deUint32)resources.inputs.size(), (formatIndex + 1) % optypeimageFormatMismatchFormatCount); |
| |
| // 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 = optypeimageFormatMismatchVkFormat[formatIndex]; |
| } |
| |
| vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE; |
| vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_FALSE; |
| createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, "shader_vert", defaultColors, defaultColors, fragments, noSpecConstants, |
| noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get()); |
| |
| createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "shader_tessc", defaultColors, defaultColors, fragments, noSpecConstants, |
| noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get()); |
| |
| createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "shader_tesse", defaultColors, defaultColors, fragments, noSpecConstants, |
| noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get()); |
| |
| createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, "shader_geom", defaultColors, defaultColors, fragments, noSpecConstants, |
| noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get()); |
| |
| vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE; |
| vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE; |
| createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, "shader_frag", defaultColors, defaultColors, fragments, noSpecConstants, |
| noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get()); |
| |
| 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()); |
| } |
| } |
| |
| 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<deUint8> 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 (deUint32 elementNdx = 0; elementNdx < static_cast<deUint32>(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 addGraphicsDepthPropertyTest (tcu::TestCaseGroup* group) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| de::Random rnd (deStringHash(group->getName())); |
| const deUint32 numDataPoints = 64; |
| RGBA defaultColors[4]; |
| vector<Vec4> inputDataVec4; |
| |
| SpecConstants noSpecConstants; |
| PushConstants noPushConstants; |
| GraphicsInterfaces noInterfaces; |
| std::vector<std::string> noExtensions; |
| VulkanFeatures vulkanFeatures = VulkanFeatures(); |
| |
| vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE; |
| vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE; |
| |
| inputDataVec4.reserve(numDataPoints); |
| |
| for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx) |
| inputDataVec4.push_back(Vec4(rnd.getFloat(), rnd.getFloat(), rnd.getFloat(), rnd.getFloat())); |
| |
| de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "depth_property", "")); |
| |
| for (deUint32 propertyNdx = 0u; propertyNdx < DEPTH_PROPERTY_LAST; propertyNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> depthPropertyGroup (new tcu::TestCaseGroup(testCtx, getDepthPropertyName((DepthProperty)propertyNdx), "")); |
| |
| for (deUint32 opNdx = 0u; opNdx < READOP_LAST; opNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> readOpGroup (new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx), "")); |
| |
| for (deUint32 descNdx = DESCRIPTOR_TYPE_SAMPLED_IMAGE; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx), "")); |
| |
| if (!isValidTestCase(TESTTYPE_LOCAL_VARIABLES, (DescriptorType)descNdx, (ReadOp)opNdx)) |
| continue; |
| |
| const VkFormat imageFormat = getImageFormat((ReadOp)opNdx); |
| const bool hasDpethComponent = tcu::hasDepthComponent(vk::mapVkFormat(imageFormat).order); |
| |
| GraphicsResources resources; |
| resources.inputFormat = imageFormat; |
| |
| std::vector<Vec4> inputData = inputDataVec4; |
| |
| // Depth images have one channel, thus only needing 1/4 of the data |
| if (hasDpethComponent) |
| inputData.resize(numDataPoints / 4u); |
| |
| 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<Vec4> dummyData; |
| resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(dummyData)), 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] = Vec4(1.0f) - inputData[i]; |
| |
| resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx))); |
| } |
| |
| // Read image without depth reference: 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)); |
| |
| // Read image with depth reference: shader is expected to pass the depth comparison result to output buffer |
| if (hasDpethComponent) |
| resources.verifyIO = verifyDepthCompareResult; |
| |
| const map<string, string> fragments = generateGraphicsImageSamplerSource((ReadOp)opNdx, (DescriptorType)descNdx, TESTTYPE_LOCAL_VARIABLES, (DepthProperty)propertyNdx, (deUint32)resources.inputs.size(), 0); |
| |
| getDefaultColors(defaultColors); |
| |
| createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, "shader_frag", defaultColors, defaultColors, fragments, noSpecConstants, |
| noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, descGroup.get()); |
| |
| readOpGroup->addChild(descGroup.release()); |
| } |
| depthPropertyGroup->addChild(readOpGroup.release()); |
| } |
| testGroup->addChild(depthPropertyGroup.release()); |
| } |
| group->addChild(testGroup.release()); |
| } |
| } // anonymous |
| |
| tcu::TestCaseGroup* createImageSamplerComputeGroup (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "image_sampler", "Compute tests for combining images and samplers.")); |
| addComputeImageSamplerTest(group.get()); |
| |
| return group.release(); |
| } |
| |
| tcu::TestCaseGroup* createImageSamplerGraphicsGroup (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "image_sampler", "Graphics tests for combining images and samplers.")); |
| |
| addGraphicsImageSamplerTest(group.get()); |
| addGraphicsDepthPropertyTest(group.get()); |
| |
| return group.release(); |
| } |
| |
| } // SpirVAssembly |
| } // vkt |