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::__anondd155b260111::Case46 Case(const char* b, bool v) : basename(b), spv1p3(v), requirements() { }
Casevkt::SpirVAssembly::__anondd155b260111::Case47 Case(const char* b, bool v, const std::vector<std::string>& e) : basename(b), spv1p3(v), requirements(e) { }
48 const char *basename;
49 bool spv1p3;
50 // Additional Vulkan requirements, if any.
51 std::vector<std::string> requirements;
52 };
53 struct CaseGroup
54 {
CaseGroupvkt::SpirVAssembly::__anondd155b260111::CaseGroup55 CaseGroup(const char* the_data_dir) : data_dir(the_data_dir) { }
addvkt::SpirVAssembly::__anondd155b260111::CaseGroup56 void add(const char* basename, bool spv1p3)
57 {
58 cases.push_back(Case(basename, spv1p3));
59 }
addvkt::SpirVAssembly::__anondd155b260111::CaseGroup60 void add(const char* basename, bool spv1p3, const std::vector<std::string>& requirements)
61 {
62 cases.push_back(Case(basename, spv1p3, requirements));
63 }
64
65 const char* data_dir;
66 std::vector<Case> cases;
67 };
68
69 #ifndef CTS_USES_VULKANSC
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_API_VERSION(0, 1, 1, 0) : VK_MAKE_API_VERSION(0, 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 category.c_str(),
88 file);
89 DE_ASSERT(testCase != DE_NULL);
90 testCase->addRequirement("VK_KHR_shader_terminate_invocation");
91 const std::vector<std::string>& reqmts = cases[i].requirements;
92 for (size_t r = 0; r < reqmts.size() ; ++r)
93 {
94 testCase->addRequirement(reqmts[r]);
95 }
96
97 testCase->setSpirVAsmBuildOptions(asm_options);
98 tests->addChild(testCase);
99 }
100 }
101
102 #endif // CTS_USES_VULKANSC
103
104 } // anonymous
105
createTerminateInvocationGroup(tcu::TestContext & testCtx)106 tcu::TestCaseGroup* createTerminateInvocationGroup(tcu::TestContext& testCtx)
107 {
108 // VK_KHR_shader_terminate_invocation tests
109 de::MovePtr<tcu::TestCaseGroup> terminateTests(new tcu::TestCaseGroup(testCtx, "terminate_invocation"));
110
111 const char* data_data = "spirv_assembly/instruction/terminate_invocation";
112
113 std::vector<std::string> Stores;
114 Stores.push_back("Features.fragmentStoresAndAtomics");
115
116 std::vector<std::string> VarPtr;
117 VarPtr.push_back("VariablePointerFeatures.variablePointersStorageBuffer");
118 VarPtr.push_back("Features.fragmentStoresAndAtomics");
119
120 std::vector<std::string> Vote;
121 Vote.push_back("SubgroupSupportedOperations.vote");
122 Vote.push_back("SubgroupSupportedStages.fragment");
123
124 std::vector<std::string> Ballot;
125 Ballot.push_back("SubgroupSupportedOperations.ballot");
126 Ballot.push_back("SubgroupSupportedStages.fragment");
127
128 CaseGroup group(data_data);
129 // no write to after calling terminate invocation
130 group.add("no_output_write", false);
131 // no write to output despite occurring before terminate invocation
132 group.add("no_output_write_before_terminate", false);
133 // no store to SSBO when it occurs after terminate invocation
134 group.add("no_ssbo_store", false, Stores);
135 // no atomic update to SSBO when it occurs after terminate invocation
136 group.add("no_ssbo_atomic", false, Stores);
137 // ssbo store commits when it occurs before terminate invocation
138 group.add("ssbo_store_before_terminate", false, Stores);
139 // no image write when it occurs after terminate invocation
140 group.add("no_image_store", false, Stores);
141 // no image atomic updates when it occurs after terminate invocation
142 group.add("no_image_atomic", false, Stores);
143 // null pointer should not be accessed by a load in a terminated invocation
144 group.add("no_null_pointer_load", false, VarPtr);
145 // null pointer should not be accessed by a store in a terminated invocation
146 group.add("no_null_pointer_store", false, VarPtr);
147 // out of bounds pointer should not be accessed by a load in a terminated invocation
148 group.add("no_out_of_bounds_load", false, VarPtr);
149 // out of bounds pointer should not be accessed by a store in a terminated invocation
150 group.add("no_out_of_bounds_store", false, VarPtr);
151 // out of bounds pointer should not be accessed by an atomic in a terminated invocation
152 group.add("no_out_of_bounds_atomic", false, VarPtr);
153 // "infinite" loop that calls terminate invocation
154 group.add("terminate_loop", false);
155 // checks that terminated invocations don't participate in the ballot
156 group.add("subgroup_ballot", true, Ballot);
157 // checks that a subgroup all does not include any terminated invocations
158 group.add("subgroup_vote", true, Vote);
159 #ifndef CTS_USES_VULKANSC
160 terminateTests->addChild(createTestGroup(testCtx, "terminate", addTestsForAmberFiles, group));
161 #endif // CTS_USES_VULKANSC
162
163 return terminateTests.release();
164 }
165
166 } // SpirVAssembly
167 } // vkt
168