xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/shaderexecutor/vktShaderClockTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2018 Advanced Micro Devices, 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 cases for VK_KHR_shader_clock. Ensure that values are
23           being read from the OpReadClockKHR OpCode.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktShaderClockTests.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vktShaderExecutor.hpp"
30 
31 #include "vkQueryUtil.hpp"
32 
33 #include "tcuStringTemplate.hpp"
34 
35 #include "vktAtomicOperationTests.hpp"
36 #include "vktShaderExecutor.hpp"
37 
38 #include "vkRefUtil.hpp"
39 #include "vkMemUtil.hpp"
40 #include "vkQueryUtil.hpp"
41 #include "vktTestGroupUtil.hpp"
42 
43 #include "tcuTestLog.hpp"
44 #include "tcuStringTemplate.hpp"
45 #include "tcuResultCollector.hpp"
46 
47 #include "deStringUtil.hpp"
48 #include "deSharedPtr.hpp"
49 #include "deRandom.hpp"
50 #include "deArrayUtil.hpp"
51 
52 #include <cassert>
53 #include <string>
54 
55 namespace vkt
56 {
57 namespace shaderexecutor
58 {
59 
60 namespace
61 {
62 
63 enum
64 {
65     NUM_ELEMENTS = 32
66 };
67 
68 enum clockType
69 {
70     SUBGROUP = 0,
71     DEVICE
72 };
73 
74 enum bitType
75 {
76     BIT_32 = 0,
77     BIT_64
78 };
79 
80 struct testType
81 {
82     clockType testClockType;
83     bitType testBitType;
84     const char *testName;
85 };
86 
getPtrOfVar(uint64_t & var)87 static inline void *getPtrOfVar(uint64_t &var)
88 {
89     return &var;
90 }
91 
92 using namespace vk;
93 
94 class ShaderClockTestInstance : public TestInstance
95 {
96 public:
ShaderClockTestInstance(Context & context,const ShaderSpec & shaderSpec,glu::ShaderType shaderType)97     ShaderClockTestInstance(Context &context, const ShaderSpec &shaderSpec, glu::ShaderType shaderType)
98         : TestInstance(context)
99         , m_executor(createExecutor(m_context, shaderType, shaderSpec))
100     {
101     }
102 
iterate(void)103     virtual tcu::TestStatus iterate(void)
104     {
105         const uint64_t initValue = 0xcdcdcdcd;
106 
107         std::vector<uint64_t> outputs(NUM_ELEMENTS, initValue);
108         std::vector<void *> outputPtr(NUM_ELEMENTS, nullptr);
109 
110         std::transform(std::begin(outputs), std::end(outputs), std::begin(outputPtr), getPtrOfVar);
111 
112         m_executor->execute(NUM_ELEMENTS, nullptr, outputPtr.data());
113 
114         if (validateOutput(outputs))
115             return tcu::TestStatus::pass("Pass");
116         else
117             return tcu::TestStatus::fail("Result comparison failed");
118     }
119 
120 private:
validateOutput(std::vector<uint64_t> & outputs)121     bool validateOutput(std::vector<uint64_t> &outputs)
122     {
123         // The shader will write a 1 in the output if the clock did not increase
124         return (outputs.size() == uint64_t(std::count(std::begin(outputs), std::end(outputs), 0)));
125     }
126 
127     de::UniquePtr<ShaderExecutor> m_executor;
128 };
129 
130 class ShaderClockCase : public TestCase
131 {
132 public:
ShaderClockCase(tcu::TestContext & testCtx,testType operation,glu::ShaderType shaderType)133     ShaderClockCase(tcu::TestContext &testCtx, testType operation, glu::ShaderType shaderType)
134         : TestCase(testCtx, operation.testName)
135         , m_operation(operation)
136         , m_shaderSpec()
137         , m_shaderType(shaderType)
138     {
139         initShaderSpec();
140     }
141 
createInstance(Context & ctx) const142     TestInstance *createInstance(Context &ctx) const override
143     {
144         return new ShaderClockTestInstance(ctx, m_shaderSpec, m_shaderType);
145     }
146 
initPrograms(vk::SourceCollections & programCollection) const147     void initPrograms(vk::SourceCollections &programCollection) const override
148     {
149         generateSources(m_shaderType, m_shaderSpec, programCollection);
150     }
151 
checkSupport(Context & context) const152     void checkSupport(Context &context) const override
153     {
154         context.requireDeviceFunctionality("VK_KHR_shader_clock");
155 
156         if (m_operation.testBitType == BIT_64)
157             context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_INT64);
158 
159         const auto &shaderClockFeatures = context.getShaderClockFeatures();
160         const auto realTimeTest         = (m_operation.testClockType == DEVICE);
161 
162         if (realTimeTest && !shaderClockFeatures.shaderDeviceClock)
163             TCU_THROW(NotSupportedError, "Shader device clock is not supported");
164 
165         if (!realTimeTest && !shaderClockFeatures.shaderSubgroupClock)
166             TCU_THROW(NotSupportedError, "Shader subgroup clock is not supported");
167     }
168 
169 private:
initShaderSpec()170     void initShaderSpec()
171     {
172         std::stringstream extensions;
173         std::stringstream source;
174 
175         if (m_operation.testBitType == BIT_64)
176         {
177             extensions << "#extension GL_ARB_gpu_shader_int64 : require        \n";
178 
179             source << "uint64_t time1 = " << m_operation.testName << "();   \n";
180             source << "uint64_t time2 = " << m_operation.testName << "();   \n";
181             source << "out0  = uvec2(0, 0);                                 \n";
182             source << "if (time1 > time2) {                                 \n";
183             source << "    out0.x = 1;                                      \n";
184             source << "}                                                    \n";
185         }
186         else
187         {
188             source << "uvec2 time1 = " << m_operation.testName << "();                      \n";
189             source << "uvec2 time2 = " << m_operation.testName << "();                      \n";
190             source << "out0  = uvec2(0, 0);                                                 \n";
191             source << "if (time1.y > time2.y || (time1.y == time2.y && time1.x > time2.x)){ \n";
192             source << "    out0.x = 1;                                                      \n";
193             source << "}                                                                    \n";
194         }
195 
196         if (m_operation.testClockType == DEVICE)
197         {
198             extensions << "#extension GL_EXT_shader_realtime_clock : require    \n";
199         }
200         else
201         {
202             extensions << "#extension GL_ARB_shader_clock : enable                \n";
203         }
204 
205         std::map<std::string, std::string> specializations = {{"EXTENSIONS", extensions.str()},
206                                                               {"SOURCE", source.str()}};
207 
208         m_shaderSpec.globalDeclarations = tcu::StringTemplate("${EXTENSIONS}").specialize(specializations);
209         m_shaderSpec.source             = tcu::StringTemplate("${SOURCE}    ").specialize(specializations);
210 
211         m_shaderSpec.outputs.push_back(Symbol("out0", glu::VarType(glu::TYPE_UINT_VEC2, glu::PRECISION_HIGHP)));
212     }
213 
214 private:
215     ShaderClockCase(const ShaderClockCase &);
216     ShaderClockCase &operator=(const ShaderClockCase &);
217 
218     testType m_operation;
219     ShaderSpec m_shaderSpec;
220     glu::ShaderType m_shaderType;
221 };
222 
addShaderClockTests(tcu::TestCaseGroup * testGroup)223 void addShaderClockTests(tcu::TestCaseGroup *testGroup)
224 {
225     static glu::ShaderType stages[] = {glu::SHADERTYPE_VERTEX, glu::SHADERTYPE_FRAGMENT, glu::SHADERTYPE_COMPUTE};
226 
227     static testType operations[] = {{SUBGROUP, BIT_64, "clockARB"},
228                                     {SUBGROUP, BIT_32, "clock2x32ARB"},
229                                     {DEVICE, BIT_64, "clockRealtimeEXT"},
230                                     {DEVICE, BIT_32, "clockRealtime2x32EXT"}};
231 
232     tcu::TestContext &testCtx = testGroup->getTestContext();
233 
234     for (size_t i = 0; i != DE_LENGTH_OF_ARRAY(stages); ++i)
235     {
236         const char *stageName = (stages[i] == glu::SHADERTYPE_VERTEX)   ? ("vertex") :
237                                 (stages[i] == glu::SHADERTYPE_FRAGMENT) ? ("fragment") :
238                                 (stages[i] == glu::SHADERTYPE_COMPUTE)  ? ("compute") :
239                                                                           (DE_NULL);
240 
241         const std::string setName = std::string() + stageName;
242         de::MovePtr<tcu::TestCaseGroup> stageGroupTest(new tcu::TestCaseGroup(testCtx, setName.c_str()));
243 
244         for (size_t j = 0; j != DE_LENGTH_OF_ARRAY(operations); ++j)
245         {
246             stageGroupTest->addChild(new ShaderClockCase(testCtx, operations[j], stages[i]));
247         }
248 
249         testGroup->addChild(stageGroupTest.release());
250     }
251 }
252 
253 } // namespace
254 
createShaderClockTests(tcu::TestContext & testCtx)255 tcu::TestCaseGroup *createShaderClockTests(tcu::TestContext &testCtx)
256 {
257     return createTestGroup(testCtx, "shader_clock", addShaderClockTests);
258 }
259 
260 } // namespace shaderexecutor
261 } // namespace vkt
262