• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief SPIR-V Float Control SPIR-V tokens test
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vkApiVersion.hpp"
25 
26 #include "vktSpvAsmFloatControlsExtensionlessTests.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktSpvAsmComputeShaderCase.hpp"
29 
30 #include "deRandom.hpp"
31 #include "deStringUtil.hpp"
32 #include "tcuCommandLine.hpp"
33 #include "vkQueryUtil.hpp"
34 
35 namespace vkt
36 {
37 namespace SpirVAssembly
38 {
39 
40 static const char* TEST_FEATURE_DENORM_PRESERVE					= "DenormPreserve";
41 static const char* TEST_FEATURE_DENORM_FLUSH_TO_ZERO			= "DenormFlushToZero";
42 static const char* TEST_FEATURE_SIGNED_ZERO_INF_NAN_PRESERVE	= "SignedZeroInfNanPreserve";
43 static const char* TEST_FEATURE_ROUNDING_MODE_RTE				= "RoundingModeRTE";
44 static const char* TEST_FEATURE_ROUNDING_MODE_RTZ				= "RoundingModeRTZ";
45 
46 using namespace vk;
47 using std::map;
48 using std::string;
49 using std::vector;
50 
getComputeSourceCode(std::string & computeSourceCode,const std::string & featureName,const int fpWideness)51 static void getComputeSourceCode (std::string& computeSourceCode, const std::string& featureName, const int fpWideness)
52 {
53 	const std::string capability	= "OpCapability " + featureName + "\n";
54 	const std::string exeModes		= "OpExecutionMode %main " + featureName + " " + de::toString(fpWideness) + "\n";
55 
56 	computeSourceCode =
57 		string(getComputeAsmShaderPreamble(capability, "", exeModes, "", "%indata %outdata")) +
58 
59 		"OpSource GLSL 430\n"
60 		"OpName %main \"main\"\n"
61 		"OpName %id \"gl_GlobalInvocationID\"\n"
62 
63 		"OpDecorate %id BuiltIn GlobalInvocationId\n"
64 
65 		+ getComputeAsmInputOutputBufferTraits("Block") + getComputeAsmCommonTypes("StorageBuffer") + getComputeAsmInputOutputBuffer("StorageBuffer") +
66 
67 		"%id        = OpVariable %uvec3ptr Input\n"
68 		"%zero      = OpConstant %i32 0\n"
69 
70 		"%main      = OpFunction %void None %voidf\n"
71 		"%label     = OpLabel\n"
72 		"%idval     = OpLoad %uvec3 %id\n"
73 		"%x         = OpCompositeExtract %u32 %idval 0\n"
74 
75 		"             OpNop\n" // Inside a function body
76 
77 		"%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
78 		"%inval     = OpLoad %f32 %inloc\n"
79 		"%neg       = OpFNegate %f32 %inval\n"
80 		"%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
81 		"             OpStore %outloc %neg\n"
82 		"             OpReturn\n"
83 		"             OpFunctionEnd\n";
84 }
85 
getComputeShaderSpec(Context & ctx,const std::string & testCaseName)86 static ComputeShaderSpec getComputeShaderSpec (Context& ctx, const std::string& testCaseName)
87 {
88 	const deUint32		baseSeed		= deStringHash(testCaseName.c_str()) + static_cast<deUint32>(ctx.getTestContext().getCommandLine().getBaseSeed());
89 	de::Random			rnd				(baseSeed);
90 	const int			numElements		= 64;
91 	vector<float>		inputFloats		(numElements, 0);
92 	vector<float>		outputFloats	(numElements, 0);
93 	ComputeShaderSpec	spec;
94 
95 	for (size_t ndx = 0; ndx < numElements; ++ndx)
96 		inputFloats[ndx] = rnd.getFloat(1.0f, 100.0f);
97 
98 	for (size_t ndx = 0; ndx < numElements; ++ndx)
99 		outputFloats[ndx] = -inputFloats[ndx];
100 
101 	// Shader source code can be retrieved to complete definition of ComputeShaderSpec, though it is not required at this stage
102 	// getComputeSourceCode (spec.assembly);
103 
104 	spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
105 	spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
106 
107 	spec.numWorkGroups	= tcu::IVec3(numElements, 1, 1);
108 	spec.verifyIO		= &verifyOutput;
109 
110 	return spec;
111 }
112 
getFloatControlsProperty(Context & context,const int fpWideness,const std::string & featureName)113 VkBool32 getFloatControlsProperty(Context& context, const int fpWideness, const std::string& featureName)
114 {
115 	VkPhysicalDeviceFloatControlsProperties floatControlsProperties;
116 	deMemset(&floatControlsProperties, 0, sizeof(floatControlsProperties));
117 	floatControlsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES;
118 
119 	VkPhysicalDeviceProperties2 properties;
120 	deMemset(&properties, 0, sizeof(properties));
121 	properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
122 	properties.pNext = &floatControlsProperties;
123 
124 	context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
125 
126 	if (fpWideness == 16)
127 	{
128 		if (featureName == TEST_FEATURE_DENORM_PRESERVE				) return floatControlsProperties.shaderDenormPreserveFloat16;
129 		if (featureName == TEST_FEATURE_DENORM_FLUSH_TO_ZERO		) return floatControlsProperties.shaderDenormFlushToZeroFloat16;
130 		if (featureName == TEST_FEATURE_SIGNED_ZERO_INF_NAN_PRESERVE) return floatControlsProperties.shaderSignedZeroInfNanPreserveFloat16;
131 		if (featureName == TEST_FEATURE_ROUNDING_MODE_RTE			) return floatControlsProperties.shaderRoundingModeRTEFloat16;
132 		if (featureName == TEST_FEATURE_ROUNDING_MODE_RTZ			) return floatControlsProperties.shaderRoundingModeRTZFloat16;
133 	}
134 
135 	if (fpWideness == 32)
136 	{
137 		if (featureName == TEST_FEATURE_DENORM_PRESERVE				) return floatControlsProperties.shaderDenormPreserveFloat32;
138 		if (featureName == TEST_FEATURE_DENORM_FLUSH_TO_ZERO		) return floatControlsProperties.shaderDenormFlushToZeroFloat32;
139 		if (featureName == TEST_FEATURE_SIGNED_ZERO_INF_NAN_PRESERVE) return floatControlsProperties.shaderSignedZeroInfNanPreserveFloat32;
140 		if (featureName == TEST_FEATURE_ROUNDING_MODE_RTE			) return floatControlsProperties.shaderRoundingModeRTEFloat32;
141 		if (featureName == TEST_FEATURE_ROUNDING_MODE_RTZ			) return floatControlsProperties.shaderRoundingModeRTZFloat32;
142 	}
143 
144 	if (fpWideness == 64)
145 	{
146 		if (featureName == TEST_FEATURE_DENORM_PRESERVE				) return floatControlsProperties.shaderDenormPreserveFloat64;
147 		if (featureName == TEST_FEATURE_DENORM_FLUSH_TO_ZERO		) return floatControlsProperties.shaderDenormFlushToZeroFloat64;
148 		if (featureName == TEST_FEATURE_SIGNED_ZERO_INF_NAN_PRESERVE) return floatControlsProperties.shaderSignedZeroInfNanPreserveFloat64;
149 		if (featureName == TEST_FEATURE_ROUNDING_MODE_RTE			) return floatControlsProperties.shaderRoundingModeRTEFloat64;
150 		if (featureName == TEST_FEATURE_ROUNDING_MODE_RTZ			) return floatControlsProperties.shaderRoundingModeRTZFloat64;
151 	}
152 
153 	TCU_THROW(InternalError, "Unknown property requested");
154 }
155 
156 class SpvAsmFloatControlsExtensionlessInstance : public ComputeShaderSpec, public SpvAsmComputeShaderInstance
157 {
158 public:
159 	SpvAsmFloatControlsExtensionlessInstance	(Context& ctx, const std::string& testCaseName);
160 };
161 
SpvAsmFloatControlsExtensionlessInstance(Context & ctx,const std::string & testCaseName)162 SpvAsmFloatControlsExtensionlessInstance::SpvAsmFloatControlsExtensionlessInstance (Context& ctx, const std::string& testCaseName)
163 	: ComputeShaderSpec(getComputeShaderSpec(ctx, testCaseName))
164 	, SpvAsmComputeShaderInstance(ctx, *this)
165 {
166 }
167 
SpvAsmFloatControlsExtensionlessCase(tcu::TestContext & testCtx,const char * name,const char * description,const char * featureName,const int fpWideness,const bool spirv14)168 SpvAsmFloatControlsExtensionlessCase::SpvAsmFloatControlsExtensionlessCase (tcu::TestContext& testCtx, const char* name, const char* description, const char* featureName, const int fpWideness, const bool spirv14)
169 	: TestCase		(testCtx, name, description)
170 	, m_featureName	(featureName)
171 	, m_fpWideness	(fpWideness)
172 	, m_spirv14		(spirv14)
173 {
174 }
175 
initPrograms(SourceCollections & programCollection) const176 void SpvAsmFloatControlsExtensionlessCase::initPrograms (SourceCollections& programCollection) const
177 {
178 	const bool	allowSpirv14	= true;
179 	std::string	comp;
180 
181 	getComputeSourceCode(comp, m_featureName, m_fpWideness);
182 
183 	programCollection.spirvAsmSources.add("compute") << SpirVAsmBuildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_4, allowSpirv14) << comp;
184 }
185 
checkSupport(Context & context) const186 void SpvAsmFloatControlsExtensionlessCase::checkSupport (Context& context) const
187 {
188 	if (m_spirv14)
189 	{
190 		context.requireDeviceFunctionality("VK_KHR_spirv_1_4");
191 	}
192 	else
193 	{
194 		if (!context.contextSupports(vk::ApiVersion(0, 1, 2, 0)))
195 			TCU_THROW(NotSupportedError, "Test requires Vulkan 1.2");
196 	}
197 
198 	if (m_fpWideness == 16)
199 	{
200 		context.requireDeviceFunctionality("VK_KHR_shader_float16_int8");
201 		const VkPhysicalDeviceShaderFloat16Int8Features& extensionFeatures = context.getShaderFloat16Int8Features();
202 		if (!extensionFeatures.shaderFloat16)
203 			TCU_THROW(NotSupportedError, "Floating point number of width 16 bit are not supported");
204 	}
205 
206 	if (m_fpWideness == 64)
207 	{
208 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_FLOAT64);
209 	}
210 
211 	if (!getFloatControlsProperty(context, m_fpWideness, m_featureName))
212 		TCU_THROW(NotSupportedError, "Property is not supported");
213 }
214 
createInstance(Context & context) const215 TestInstance* SpvAsmFloatControlsExtensionlessCase::createInstance (Context& context) const
216 {
217 	return new SpvAsmFloatControlsExtensionlessInstance(context, getName());
218 }
219 
createFloatControlsExtensionlessGroup(tcu::TestContext & testCtx)220 tcu::TestCaseGroup* createFloatControlsExtensionlessGroup (tcu::TestContext& testCtx)
221 {
222 	const char*						spirVersions[]			= { "spirv1p4", "vulkan1_2" };
223 	const int						floatingPointWideness[]	= { 16, 32, 64 };
224 	const struct FpFeatures
225 	{
226 		const char* testName;
227 		const char* featureName;
228 	}
229 	fpFeatures[] =
230 	{
231 		{ "denorm_preserve",				TEST_FEATURE_DENORM_PRESERVE				},
232 		{ "denorm_flush_to_zero",			TEST_FEATURE_DENORM_FLUSH_TO_ZERO			},
233 		{ "signed_zero_inf_nan_preserve",	TEST_FEATURE_SIGNED_ZERO_INF_NAN_PRESERVE	},
234 		{ "rounding_mode_rte",				TEST_FEATURE_ROUNDING_MODE_RTE				},
235 		{ "rounding_mode_rtz",				TEST_FEATURE_ROUNDING_MODE_RTZ				},
236 	};
237 	de::MovePtr<tcu::TestCaseGroup>	group					(new tcu::TestCaseGroup(testCtx, "float_controls_extensionless", "Tests float controls without extension"));
238 
239 	for (int spirVersionsNdx = 0; spirVersionsNdx < DE_LENGTH_OF_ARRAY(spirVersions); ++spirVersionsNdx)
240 	{
241 		const bool						spirv14				= (spirVersionsNdx == 0);
242 		de::MovePtr<tcu::TestCaseGroup>	spirVersionGroup	(new tcu::TestCaseGroup(testCtx, spirVersions[spirVersionsNdx], ""));
243 
244 		for (int fpWidenessNdx = 0; fpWidenessNdx < DE_LENGTH_OF_ARRAY(floatingPointWideness); ++fpWidenessNdx)
245 		for (int execModeNdx = 0; execModeNdx < DE_LENGTH_OF_ARRAY(fpFeatures); ++execModeNdx)
246 		{
247 			const int			fpWideness		= floatingPointWideness[fpWidenessNdx];
248 			const std::string	testName		= fpFeatures[execModeNdx].testName;
249 			const char*			featureName		= fpFeatures[execModeNdx].featureName;
250 			const std::string	fullTestName	= "fp" + de::toString(fpWideness) + "_" + testName;
251 
252 			spirVersionGroup->addChild(new SpvAsmFloatControlsExtensionlessCase(testCtx, fullTestName.c_str(), "", featureName, fpWideness, spirv14));
253 		}
254 
255 		group->addChild(spirVersionGroup.release());
256 	}
257 
258 	return group.release();
259 }
260 
261 
262 } // SpirVAssembly
263 } // vkt
264