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