• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(deUint64 & var)87 static inline void* getPtrOfVar(deUint64& 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 deUint64 initValue = 0xcdcdcdcd;
106 
107 		std::vector<deUint64>	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<deUint64> & outputs)121 	bool validateOutput(std::vector<deUint64>& outputs)
122 	{
123 		// The shader will write a 1 in the output if the clock did not increase
124 		return (outputs.size() == deUint64(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, 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 = {
206 			{	"EXTENSIONS",	extensions.str()    },
207 			{	"SOURCE",		source.str()        }
208 		};
209 
210 		m_shaderSpec.globalDeclarations = tcu::StringTemplate("${EXTENSIONS}").specialize(specializations);
211 		m_shaderSpec.source             = tcu::StringTemplate("${SOURCE}	").specialize(specializations);
212 
213 		m_shaderSpec.outputs.push_back(Symbol("out0", glu::VarType(glu::TYPE_UINT_VEC2, glu::PRECISION_HIGHP)));
214 	}
215 
216 private:
217 	ShaderClockCase				(const ShaderClockCase&);
218 	ShaderClockCase& operator=	(const ShaderClockCase&);
219 
220 	testType							m_operation;
221 	ShaderSpec							m_shaderSpec;
222 	glu::ShaderType						m_shaderType;
223 };
224 
addShaderClockTests(tcu::TestCaseGroup * testGroup)225 void addShaderClockTests (tcu::TestCaseGroup* testGroup)
226 {
227 	static glu::ShaderType stages[] =
228 	{
229 		glu::SHADERTYPE_VERTEX,
230 		glu::SHADERTYPE_FRAGMENT,
231 		glu::SHADERTYPE_COMPUTE
232 	};
233 
234 	static testType operations[] =
235     {
236 		{SUBGROUP, BIT_64, "clockARB"},
237 		{SUBGROUP, BIT_32, "clock2x32ARB" },
238 		{DEVICE,   BIT_64, "clockRealtimeEXT"},
239 		{DEVICE,   BIT_32, "clockRealtime2x32EXT"}
240 	};
241 
242 	tcu::TestContext& testCtx = testGroup->getTestContext();
243 
244 	for (size_t i = 0; i != DE_LENGTH_OF_ARRAY(stages); ++i)
245 	{
246 		const char* stageName = (stages[i] == glu::SHADERTYPE_VERTEX) ? ("vertex")
247 								: (stages[i] == glu::SHADERTYPE_FRAGMENT) ? ("fragment")
248 								: (stages[i] == glu::SHADERTYPE_COMPUTE) ? ("compute")
249 								: (DE_NULL);
250 
251 		const std::string setName = std::string() + stageName;
252 		de::MovePtr<tcu::TestCaseGroup> stageGroupTest(new tcu::TestCaseGroup(testCtx, setName.c_str(), "Shader Clock Tests"));
253 
254 		for (size_t j = 0; j != DE_LENGTH_OF_ARRAY(operations); ++j)
255 		{
256 			stageGroupTest->addChild(new ShaderClockCase(testCtx, operations[j], stages[i]));
257 		}
258 
259 		testGroup->addChild(stageGroupTest.release());
260 	}
261 }
262 
263 } // anonymous
264 
createShaderClockTests(tcu::TestContext & testCtx)265 tcu::TestCaseGroup* createShaderClockTests(tcu::TestContext& testCtx)
266 {
267 	return createTestGroup(testCtx, "shader_clock", "Shader Clock Tests", addShaderClockTests);
268 }
269 
270 } // shaderexecutor
271 } // vkt
272