1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 Google 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 Assembly Tests for varying names.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSpvAsmVaryingNameTests.hpp"
25 #include "vktSpvAsmComputeShaderCase.hpp"
26 #include "vktSpvAsmComputeShaderTestUtil.hpp"
27 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
28 
29 namespace vkt
30 {
31 namespace SpirVAssembly
32 {
33 
34 using namespace vk;
35 using std::map;
36 using std::string;
37 using std::vector;
38 using tcu::RGBA;
39 
40 namespace
41 {
42 
43 struct TestParams
44 {
45 	string											name;
46 	FunctionPrograms1<InstanceContext>::Function	createShaders;
47 };
48 
createShaders(SourceCollections & dst,InstanceContext & context,string dataNameVertShader,string dataNameFragShader)49 void createShaders (SourceCollections& dst, InstanceContext& context, string dataNameVertShader, string dataNameFragShader)
50 {
51 	SpirvVersion	targetSpirvVersion	= context.resources.spirvVersion;
52 	const deUint32	vulkanVersion		= dst.usedVulkanVersion;
53 	const string	opNameVert			= dataNameVertShader.empty() ? "" : string("                             OpName %dataOut \"") + dataNameVertShader + "\"\n";
54 	const string	opNameFrag			= dataNameFragShader.empty() ? "" : string("                        OpName %dataIn \"") + dataNameFragShader + "\"\n";
55 
56 	// A float data of 1.0 is passed from vertex shader to fragment shader. This test checks the
57 	// mapping between shaders is based on location index and not using the name of the varying.
58 	// Variations of this test include same OpName in both shader, different OpNames and no
59 	// OpNames at all.
60 	const string	vertexShader		= string(
61 		"                             OpCapability Shader\n"
62 		"                        %1 = OpExtInstImport \"GLSL.std.450\"\n"
63 		"                             OpMemoryModel Logical GLSL450\n"
64 		"                             OpEntryPoint Vertex %main \"main\" %_ %position %vtxColor %color %dataOut\n"
65 		"                             OpSource GLSL 450\n"
66 		"                             OpName %main \"main\"\n"
67 		"                             OpName %gl_PerVertex \"gl_PerVertex\"\n"
68 		"                             OpMemberName %gl_PerVertex 0 \"gl_Position\"\n"
69 		"                             OpMemberName %gl_PerVertex 1 \"gl_PointSize\"\n"
70 		"                             OpMemberName %gl_PerVertex 2 \"gl_ClipDistance\"\n"
71 		"                             OpMemberName %gl_PerVertex 3 \"gl_CullDistance\"\n"
72 		"                             OpName %_ \"\"\n"
73 		"                             OpName %position \"position\"\n"
74 		"                             OpName %vtxColor \"vtxColor\"\n"
75 		"                             OpName %color \"color\"\n")
76 		+ opNameVert +
77 		"                             OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n"
78 		"                             OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n"
79 		"                             OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n"
80 		"                             OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance\n"
81 		"                             OpDecorate %gl_PerVertex Block\n"
82 		"                             OpDecorate %position Location 0\n"
83 		"                             OpDecorate %vtxColor Location 1\n"
84 		"                             OpDecorate %color Location 1\n"
85 		"                             OpDecorate %dataOut Location 0\n"
86 		"                     %void = OpTypeVoid\n"
87 		"                        %3 = OpTypeFunction %void\n"
88 		"                    %float = OpTypeFloat 32\n"
89 		"                  %v4float = OpTypeVector %float 4\n"
90 		"                     %uint = OpTypeInt 32 0\n"
91 		"                   %uint_1 = OpConstant %uint 1\n"
92 		"        %_arr_float_uint_1 = OpTypeArray %float %uint_1\n"
93 		"             %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1\n"
94 		" %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n"
95 		"                        %_ = OpVariable %_ptr_Output_gl_PerVertex Output\n"
96 		"                      %int = OpTypeInt 32 1\n"
97 		"                    %int_0 = OpConstant %int 0\n"
98 		"       %_ptr_Input_v4float = OpTypePointer Input %v4float\n"
99 		"                 %position = OpVariable %_ptr_Input_v4float Input\n"
100 		"      %_ptr_Output_v4float = OpTypePointer Output %v4float\n"
101 		"                 %vtxColor = OpVariable %_ptr_Output_v4float Output\n"
102 		"                    %color = OpVariable %_ptr_Input_v4float Input\n"
103 		"        %_ptr_Output_float = OpTypePointer Output %float\n"
104 		"                  %dataOut = OpVariable %_ptr_Output_float Output\n"
105 		"                  %float_1 = OpConstant %float 1\n"
106 		"                     %main = OpFunction %void None %3\n"
107 		"                        %5 = OpLabel\n"
108 		"                       %18 = OpLoad %v4float %position\n"
109 		"                       %20 = OpAccessChain %_ptr_Output_v4float %_ %int_0\n"
110 		"                             OpStore %20 %18\n"
111 		"                       %23 = OpLoad %v4float %color\n"
112 		"                             OpStore %vtxColor %23\n"
113 		"                             OpStore %dataOut %float_1\n"
114 		"                             OpReturn\n"
115 		"                             OpFunctionEnd\n";
116 
117 	const string	fragmentShader		= string(
118 		"                        OpCapability Shader\n"
119 		"                   %1 = OpExtInstImport \"GLSL.std.450\"\n"
120 		"                        OpMemoryModel Logical GLSL450\n"
121 		"                        OpEntryPoint Fragment %main \"main\" %dataIn %fragColor %vtxColor\n"
122 		"                        OpExecutionMode %main OriginUpperLeft\n"
123 		"                        OpSource GLSL 450\n"
124 		"                        OpName %main \"main\"\n"
125 		"                        OpName %Output \"Output\"\n"
126 		"                        OpMemberName %Output 0 \"dataOut\"\n"
127 		"                        OpName %dataOutput \"dataOutput\"\n")
128 		+ opNameFrag +
129 		"                        OpName %fragColor \"fragColor\"\n"
130 		"                        OpName %vtxColor \"vtxColor\"\n"
131 		"                        OpMemberDecorate %Output 0 Offset 0\n"
132 		"                        OpDecorate %Output BufferBlock\n"
133 		"                        OpDecorate %dataOutput DescriptorSet 0\n"
134 		"                        OpDecorate %dataOutput Binding 0\n"
135 		"                        OpDecorate %dataIn Location 0\n"
136 		"                        OpDecorate %fragColor Location 0\n"
137 		"                        OpDecorate %vtxColor Location 1\n"
138 		"                %void = OpTypeVoid\n"
139 		"                   %3 = OpTypeFunction %void\n"
140 		"               %float = OpTypeFloat 32\n"
141 		"              %Output = OpTypeStruct %float\n"
142 		" %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
143 		"          %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
144 		"                 %int = OpTypeInt 32 1\n"
145 		"               %int_0 = OpConstant %int 0\n"
146 		"    %_ptr_Input_float = OpTypePointer Input %float\n"
147 		"              %dataIn = OpVariable %_ptr_Input_float Input\n"
148 		"  %_ptr_Uniform_float = OpTypePointer Uniform %float\n"
149 		"             %v4float = OpTypeVector %float 4\n"
150 		" %_ptr_Output_v4float = OpTypePointer Output %v4float\n"
151 		"           %fragColor = OpVariable %_ptr_Output_v4float Output\n"
152 		"  %_ptr_Input_v4float = OpTypePointer Input %v4float\n"
153 		"            %vtxColor = OpVariable %_ptr_Input_v4float Input\n"
154 		"                %main = OpFunction %void None %3\n"
155 		"                   %5 = OpLabel\n"
156 		"                  %14 = OpLoad %float %dataIn\n"
157 		"                  %16 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0\n"
158 		"                        OpStore %16 %14\n"
159 		"                  %22 = OpLoad %v4float %vtxColor\n"
160 		"                        OpStore %fragColor %22\n"
161 		"                        OpReturn\n"
162 		"                        OpFunctionEnd\n";
163 
164 	dst.spirvAsmSources.add("vert", DE_NULL) << vertexShader << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
165 	dst.spirvAsmSources.add("frag", DE_NULL) << fragmentShader << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
166 }
167 
createShadersNamesMatch(vk::SourceCollections & dst,InstanceContext context)168 void createShadersNamesMatch (vk::SourceCollections& dst, InstanceContext context)
169 {
170 	createShaders(dst, context, "data", "data");
171 }
172 
createShadersNamesDiffer(vk::SourceCollections & dst,InstanceContext context)173 void createShadersNamesDiffer (vk::SourceCollections& dst, InstanceContext context)
174 {
175 	createShaders(dst, context, "dataOut", "dataIn");
176 }
177 
createShadersNoNames(vk::SourceCollections & dst,InstanceContext context)178 void createShadersNoNames (vk::SourceCollections& dst, InstanceContext context)
179 {
180 	createShaders(dst, context, "", "");
181 }
182 
addGraphicsVaryingNameTest(tcu::TestCaseGroup * group,const TestParams & params)183 void addGraphicsVaryingNameTest (tcu::TestCaseGroup* group, const TestParams& params)
184 {
185 	map<string, string>		fragments;
186 	RGBA					defaultColors[4];
187 	SpecConstants			noSpecConstants;
188 	PushConstants			noPushConstants;
189 	GraphicsInterfaces		noInterfaces;
190 	vector<string>			extensions;
191 	VulkanFeatures			features;
192 	map<string, string>		noFragments;
193 	StageToSpecConstantMap	specConstantMap;
194 	GraphicsResources		resources;
195 	const vector<float>		expectedOutput(1, 1.0f);
196 
197 	const ShaderElement		pipelineStages[]	=
198 	{
199 		ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
200 		ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
201 	};
202 
203 	specConstantMap[VK_SHADER_STAGE_VERTEX_BIT]		= noSpecConstants;
204 	specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT]	= noSpecConstants;
205 
206 	getDefaultColors(defaultColors);
207 
208 	features.coreFeatures.fragmentStoresAndAtomics = VK_TRUE;
209 	extensions.push_back("VK_KHR_storage_buffer_storage_class");
210 
211 	resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
212 
213 	{
214 		const InstanceContext& instanceContext = createInstanceContext(pipelineStages,
215 				defaultColors,
216 				defaultColors,
217 				noFragments,
218 				specConstantMap,
219 				noPushConstants,
220 				resources,
221 				noInterfaces,
222 				extensions,
223 				features,
224 				VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
225 				QP_TEST_RESULT_FAIL,
226 				string());
227 
228 		addFunctionCaseWithPrograms<InstanceContext>(group,
229 				params.name.c_str(),
230 				"",
231 				params.createShaders,
232 				runAndVerifyDefaultPipeline,
233 				instanceContext);
234 	}
235 }
236 
237 } // anonymous
238 
createVaryingNameGraphicsGroup(tcu::TestContext & testCtx)239 tcu::TestCaseGroup* createVaryingNameGraphicsGroup (tcu::TestContext& testCtx)
240 {
241 	de::MovePtr<tcu::TestCaseGroup>	group		(new tcu::TestCaseGroup(testCtx, "varying_name", "Graphics tests for varying names."));
242 
243 	static const TestParams			params[]	=
244 	{
245 		{ "names_match",	createShadersNamesMatch		},
246 		{ "names_differ",	createShadersNamesDiffer	},
247 		{ "no_names",		createShadersNoNames		}
248 	};
249 
250 	for (deUint32 paramIdx = 0; paramIdx < DE_LENGTH_OF_ARRAY(params); paramIdx++)
251 		addGraphicsVaryingNameTest(group.get(), params[paramIdx]);
252 
253 	return group.release();
254 }
255 
256 } // SpirVAssembly
257 } // vkt
258