1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 Google LLC
6  * Copyright (c) 2020 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Test new features in VK_KHR_shader_terminate_invocation
23  *//*--------------------------------------------------------------------*/
24 
25 #include <string>
26 #include <vector>
27 #include <amber/amber.h>
28 
29 #include "tcuDefs.hpp"
30 
31 #include "vkDefs.hpp"
32 #include "vktTestGroupUtil.hpp"
33 #include "vktAmberTestCase.hpp"
34 #include "vktSpvAsmTerminateInvocationTests.hpp"
35 #include "vktTestGroupUtil.hpp"
36 
37 namespace vkt
38 {
39 namespace SpirVAssembly
40 {
41 namespace
42 {
43 
44 struct Case
45 {
Casevkt::SpirVAssembly::__anon755405860111::Case46 	Case(const char* b, const char* d, bool v) : basename(b), description(d), spv1p3(v), requirements() { }
Casevkt::SpirVAssembly::__anon755405860111::Case47 	Case(const char* b, const char* d, bool v, const std::vector<std::string>& e) : basename(b), description(d), spv1p3(v), requirements(e) { }
48 	const char *basename;
49 	const char *description;
50 	bool spv1p3;
51 	// Additional Vulkan requirements, if any.
52 	std::vector<std::string> requirements;
53 };
54 struct CaseGroup
55 {
CaseGroupvkt::SpirVAssembly::__anon755405860111::CaseGroup56 	CaseGroup(const char* the_data_dir) : data_dir(the_data_dir) { }
addvkt::SpirVAssembly::__anon755405860111::CaseGroup57 	void add(const char* basename, const char* description, bool spv1p3)
58 	{
59 		cases.push_back(Case(basename, description, spv1p3));
60 	}
addvkt::SpirVAssembly::__anon755405860111::CaseGroup61 	void add(const char* basename, const char* description, bool spv1p3, const std::vector<std::string>& requirements)
62 	{
63 		cases.push_back(Case(basename, description, spv1p3, requirements));
64 	}
65 
66 	const char* data_dir;
67 	std::vector<Case> cases;
68 };
69 
70 
addTestsForAmberFiles(tcu::TestCaseGroup * tests,CaseGroup group)71 void addTestsForAmberFiles (tcu::TestCaseGroup* tests, CaseGroup group)
72 {
73 	tcu::TestContext& testCtx = tests->getTestContext();
74 	const std::string data_dir(group.data_dir);
75 	const std::string category = data_dir;
76 	std::vector<Case> cases(group.cases);
77 
78 	for (unsigned i = 0; i < cases.size() ; ++i)
79 	{
80 		deUint32 vulkan_version = cases[i].spv1p3 ? VK_MAKE_VERSION(1, 1, 0) : VK_MAKE_VERSION(1, 0, 0);
81 		vk::SpirvVersion spirv_version = cases[i].spv1p3 ? vk::SPIRV_VERSION_1_3 : vk::SPIRV_VERSION_1_0;
82 		vk::SpirVAsmBuildOptions asm_options(vulkan_version, spirv_version);
83 
84 		const std::string file = std::string(cases[i].basename) + ".amber";
85 		cts_amber::AmberTestCase *testCase = cts_amber::createAmberTestCase(testCtx,
86 																			cases[i].basename,
87 																			cases[i].description,
88 																			category.c_str(),
89 																			file);
90 		DE_ASSERT(testCase != DE_NULL);
91 		testCase->addRequirement("VK_KHR_shader_terminate_invocation");
92 		const std::vector<std::string>& reqmts = cases[i].requirements;
93 		for (size_t r = 0; r < reqmts.size() ; ++r)
94 		{
95 			testCase->addRequirement(reqmts[r]);
96 		}
97 
98 		testCase->setSpirVAsmBuildOptions(asm_options);
99 		tests->addChild(testCase);
100 	}
101 }
102 
103 } // anonymous
104 
createTerminateInvocationGroup(tcu::TestContext & testCtx)105 tcu::TestCaseGroup* createTerminateInvocationGroup(tcu::TestContext& testCtx)
106 {
107 	de::MovePtr<tcu::TestCaseGroup> terminateTests(new tcu::TestCaseGroup(testCtx, "terminate_invocation", "VK_KHR_shader_terminate_invocation tests"));
108 
109 	const char* data_data = "spirv_assembly/instruction/terminate_invocation";
110 
111 	std::vector<std::string> Stores;
112 	Stores.push_back("Features.fragmentStoresAndAtomics");
113 
114 	std::vector<std::string> VarPtr;
115 	VarPtr.push_back("VariablePointerFeatures.variablePointersStorageBuffer");
116 	VarPtr.push_back("Features.fragmentStoresAndAtomics");
117 
118 	std::vector<std::string> Vote;
119 	Vote.push_back("SubgroupProperties.supportedOperations.vote");
120 	Vote.push_back("SubgroupProperties.supportedStages.fragment");
121 
122 	std::vector<std::string> Ballot;
123 	Ballot.push_back("SubgroupProperties.supportedOperations.ballot");
124 	Ballot.push_back("SubgroupProperties.supportedStages.fragment");
125 
126 	CaseGroup group(data_data);
127 	group.add("no_output_write", "no write to after calling terminate invocation", false);
128 	group.add("no_output_write_before_terminate", "no write to output despite occurring before terminate invocation", false);
129 	group.add("no_ssbo_store", "no store to SSBO when it occurs after terminate invocation", false, Stores);
130 	group.add("no_ssbo_atomic", "no atomic update to SSBO when it occurs after terminate invocation", false, Stores);
131 	group.add("ssbo_store_before_terminate", "ssbo store commits when it occurs before terminate invocation", false, Stores);
132 	group.add("no_image_store", "no image write when it occurs after terminate invocation", false, Stores);
133 	group.add("no_image_atomic", "no image atomic updates when it occurs after terminate invocation", false, Stores);
134 	group.add("no_null_pointer_load", "null pointer should not be accessed by a load in a terminated invocation", false, VarPtr);
135 	group.add("no_null_pointer_store", "null pointer should not be accessed by a store in a terminated invocation", false, VarPtr);
136 	group.add("no_out_of_bounds_load", "out of bounds pointer should not be accessed by a load in a terminated invocation", false, VarPtr);
137 	group.add("no_out_of_bounds_store", "out of bounds pointer should not be accessed by a store in a terminated invocation", false, VarPtr);
138 	group.add("no_out_of_bounds_atomic", "out of bounds pointer should not be accessed by an atomic in a terminated invocation", false, VarPtr);
139 	group.add("terminate_loop", "\"inifinite\" loop that calls terminate invocation", false);
140 	group.add("subgroup_ballot", "checks that terminated invocations don't participate in the ballot", true, Ballot);
141 	group.add("subgroup_vote", "checks that a subgroup all does not include any terminated invocations", true, Vote);
142 	terminateTests->addChild(createTestGroup(testCtx, "terminate", "Terminate Invocation", addTestsForAmberFiles, group));
143 
144 	return terminateTests.release();
145 }
146 
147 } // SpirVAssembly
148 } // vkt
149