1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2015 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2018 Advanced Micro Devices, Inc.
7e5c31af7Sopenharmony_ci *
8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
11e5c31af7Sopenharmony_ci *
12e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
13e5c31af7Sopenharmony_ci *
14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
18e5c31af7Sopenharmony_ci * limitations under the License.
19e5c31af7Sopenharmony_ci *
20e5c31af7Sopenharmony_ci *//*!
21e5c31af7Sopenharmony_ci * \file
22e5c31af7Sopenharmony_ci * \brief Test cases for VK_KHR_shader_clock. Ensure that values are
23e5c31af7Sopenharmony_ci          being read from the OpReadClockKHR OpCode.
24e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "vktShaderClockTests.hpp"
27e5c31af7Sopenharmony_ci#include "vktTestCaseUtil.hpp"
28e5c31af7Sopenharmony_ci#include "vktTestGroupUtil.hpp"
29e5c31af7Sopenharmony_ci#include "vktShaderExecutor.hpp"
30e5c31af7Sopenharmony_ci
31e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
32e5c31af7Sopenharmony_ci
33e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_ci#include "vktAtomicOperationTests.hpp"
36e5c31af7Sopenharmony_ci#include "vktShaderExecutor.hpp"
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp"
39e5c31af7Sopenharmony_ci#include "vkMemUtil.hpp"
40e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
41e5c31af7Sopenharmony_ci#include "vktTestGroupUtil.hpp"
42e5c31af7Sopenharmony_ci
43e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
44e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
45e5c31af7Sopenharmony_ci#include "tcuResultCollector.hpp"
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
48e5c31af7Sopenharmony_ci#include "deSharedPtr.hpp"
49e5c31af7Sopenharmony_ci#include "deRandom.hpp"
50e5c31af7Sopenharmony_ci#include "deArrayUtil.hpp"
51e5c31af7Sopenharmony_ci
52e5c31af7Sopenharmony_ci#include <cassert>
53e5c31af7Sopenharmony_ci#include <string>
54e5c31af7Sopenharmony_ci
55e5c31af7Sopenharmony_cinamespace vkt
56e5c31af7Sopenharmony_ci{
57e5c31af7Sopenharmony_cinamespace shaderexecutor
58e5c31af7Sopenharmony_ci{
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_cinamespace
61e5c31af7Sopenharmony_ci{
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_cienum
64e5c31af7Sopenharmony_ci{
65e5c31af7Sopenharmony_ci	NUM_ELEMENTS = 32
66e5c31af7Sopenharmony_ci};
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_cienum clockType
69e5c31af7Sopenharmony_ci{
70e5c31af7Sopenharmony_ci	SUBGROUP = 0,
71e5c31af7Sopenharmony_ci	DEVICE
72e5c31af7Sopenharmony_ci};
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_cienum bitType
75e5c31af7Sopenharmony_ci{
76e5c31af7Sopenharmony_ci	BIT_32 = 0,
77e5c31af7Sopenharmony_ci	BIT_64
78e5c31af7Sopenharmony_ci};
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_cistruct testType
81e5c31af7Sopenharmony_ci{
82e5c31af7Sopenharmony_ci	clockType   testClockType;
83e5c31af7Sopenharmony_ci	bitType     testBitType;
84e5c31af7Sopenharmony_ci	const char* testName;
85e5c31af7Sopenharmony_ci};
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_cistatic inline void* getPtrOfVar(deUint64& var)
88e5c31af7Sopenharmony_ci{
89e5c31af7Sopenharmony_ci	return &var;
90e5c31af7Sopenharmony_ci}
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ciusing namespace vk;
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ciclass ShaderClockTestInstance : public TestInstance
95e5c31af7Sopenharmony_ci{
96e5c31af7Sopenharmony_cipublic:
97e5c31af7Sopenharmony_ci	ShaderClockTestInstance(Context& context, const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
98e5c31af7Sopenharmony_ci		: TestInstance(context)
99e5c31af7Sopenharmony_ci		, m_executor(createExecutor(m_context, shaderType, shaderSpec))
100e5c31af7Sopenharmony_ci	{
101e5c31af7Sopenharmony_ci	}
102e5c31af7Sopenharmony_ci
103e5c31af7Sopenharmony_ci	virtual tcu::TestStatus iterate(void)
104e5c31af7Sopenharmony_ci	{
105e5c31af7Sopenharmony_ci		const deUint64 initValue = 0xcdcdcdcd;
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci		std::vector<deUint64>	outputs		(NUM_ELEMENTS, initValue);
108e5c31af7Sopenharmony_ci		std::vector<void*>		outputPtr	(NUM_ELEMENTS, nullptr);
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci		std::transform(std::begin(outputs), std::end(outputs), std::begin(outputPtr), getPtrOfVar);
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_ci		m_executor->execute(NUM_ELEMENTS, nullptr, outputPtr.data());
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ci		if (validateOutput(outputs))
115e5c31af7Sopenharmony_ci			return tcu::TestStatus::pass("Pass");
116e5c31af7Sopenharmony_ci		else
117e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail("Result comparison failed");
118e5c31af7Sopenharmony_ci	}
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ciprivate:
121e5c31af7Sopenharmony_ci	bool validateOutput(std::vector<deUint64>& outputs)
122e5c31af7Sopenharmony_ci	{
123e5c31af7Sopenharmony_ci		// The shader will write a 1 in the output if the clock did not increase
124e5c31af7Sopenharmony_ci		return (outputs.size() == deUint64(std::count(std::begin(outputs), std::end(outputs), 0)));
125e5c31af7Sopenharmony_ci	}
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci	de::UniquePtr<ShaderExecutor>		m_executor;
128e5c31af7Sopenharmony_ci};
129e5c31af7Sopenharmony_ci
130e5c31af7Sopenharmony_ciclass ShaderClockCase : public TestCase
131e5c31af7Sopenharmony_ci{
132e5c31af7Sopenharmony_cipublic:
133e5c31af7Sopenharmony_ci	ShaderClockCase(tcu::TestContext& testCtx, testType operation, glu::ShaderType shaderType)
134e5c31af7Sopenharmony_ci		: TestCase(testCtx, operation.testName)
135e5c31af7Sopenharmony_ci		, m_operation(operation)
136e5c31af7Sopenharmony_ci		, m_shaderSpec()
137e5c31af7Sopenharmony_ci		, m_shaderType(shaderType)
138e5c31af7Sopenharmony_ci	{
139e5c31af7Sopenharmony_ci		initShaderSpec();
140e5c31af7Sopenharmony_ci	}
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_ci	TestInstance* createInstance (Context& ctx) const override
143e5c31af7Sopenharmony_ci	{
144e5c31af7Sopenharmony_ci		return new ShaderClockTestInstance(ctx, m_shaderSpec, m_shaderType);
145e5c31af7Sopenharmony_ci	}
146e5c31af7Sopenharmony_ci
147e5c31af7Sopenharmony_ci	void initPrograms (vk::SourceCollections& programCollection) const override
148e5c31af7Sopenharmony_ci	{
149e5c31af7Sopenharmony_ci		generateSources(m_shaderType, m_shaderSpec, programCollection);
150e5c31af7Sopenharmony_ci	}
151e5c31af7Sopenharmony_ci
152e5c31af7Sopenharmony_ci	void checkSupport (Context& context) const override
153e5c31af7Sopenharmony_ci	{
154e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_shader_clock");
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci		if (m_operation.testBitType == BIT_64)
157e5c31af7Sopenharmony_ci			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_INT64);
158e5c31af7Sopenharmony_ci
159e5c31af7Sopenharmony_ci		const auto&	shaderClockFeatures	= context.getShaderClockFeatures();
160e5c31af7Sopenharmony_ci		const auto	realTimeTest		= (m_operation.testClockType == DEVICE);
161e5c31af7Sopenharmony_ci
162e5c31af7Sopenharmony_ci		if (realTimeTest && !shaderClockFeatures.shaderDeviceClock)
163e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Shader device clock is not supported");
164e5c31af7Sopenharmony_ci
165e5c31af7Sopenharmony_ci		if (!realTimeTest && !shaderClockFeatures.shaderSubgroupClock)
166e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Shader subgroup clock is not supported");
167e5c31af7Sopenharmony_ci	}
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_ciprivate:
170e5c31af7Sopenharmony_ci	void initShaderSpec()
171e5c31af7Sopenharmony_ci	{
172e5c31af7Sopenharmony_ci		std::stringstream extensions;
173e5c31af7Sopenharmony_ci		std::stringstream source;
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_ci		if (m_operation.testBitType == BIT_64)
176e5c31af7Sopenharmony_ci		{
177e5c31af7Sopenharmony_ci			extensions	<< "#extension GL_ARB_gpu_shader_int64 : require        \n";
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_ci			source << "uint64_t time1 = " << m_operation.testName << "();   \n";
180e5c31af7Sopenharmony_ci			source << "uint64_t time2 = " << m_operation.testName << "();   \n";
181e5c31af7Sopenharmony_ci			source << "out0  = uvec2(0, 0);                                 \n";
182e5c31af7Sopenharmony_ci			source << "if (time1 > time2) {                                 \n";
183e5c31af7Sopenharmony_ci			source << "    out0.x = 1;                                      \n";
184e5c31af7Sopenharmony_ci			source << "}                                                    \n";
185e5c31af7Sopenharmony_ci		}
186e5c31af7Sopenharmony_ci		else
187e5c31af7Sopenharmony_ci		{
188e5c31af7Sopenharmony_ci			source << "uvec2 time1 = " << m_operation.testName << "();                      \n";
189e5c31af7Sopenharmony_ci			source << "uvec2 time2 = " << m_operation.testName << "();                      \n";
190e5c31af7Sopenharmony_ci			source << "out0  = uvec2(0, 0);                                                 \n";
191e5c31af7Sopenharmony_ci			source << "if (time1.y > time2.y || (time1.y == time2.y && time1.x > time2.x)){ \n";
192e5c31af7Sopenharmony_ci			source << "    out0.x = 1;                                                      \n";
193e5c31af7Sopenharmony_ci			source << "}                                                                    \n";
194e5c31af7Sopenharmony_ci		}
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_ci		if (m_operation.testClockType == DEVICE)
197e5c31af7Sopenharmony_ci		{
198e5c31af7Sopenharmony_ci			extensions << "#extension GL_EXT_shader_realtime_clock : require	\n";
199e5c31af7Sopenharmony_ci		}
200e5c31af7Sopenharmony_ci		else
201e5c31af7Sopenharmony_ci		{
202e5c31af7Sopenharmony_ci			extensions << "#extension GL_ARB_shader_clock : enable				\n";
203e5c31af7Sopenharmony_ci		}
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci		std::map<std::string, std::string> specializations = {
206e5c31af7Sopenharmony_ci			{	"EXTENSIONS",	extensions.str()    },
207e5c31af7Sopenharmony_ci			{	"SOURCE",		source.str()        }
208e5c31af7Sopenharmony_ci		};
209e5c31af7Sopenharmony_ci
210e5c31af7Sopenharmony_ci		m_shaderSpec.globalDeclarations = tcu::StringTemplate("${EXTENSIONS}").specialize(specializations);
211e5c31af7Sopenharmony_ci		m_shaderSpec.source             = tcu::StringTemplate("${SOURCE}	").specialize(specializations);
212e5c31af7Sopenharmony_ci
213e5c31af7Sopenharmony_ci		m_shaderSpec.outputs.push_back(Symbol("out0", glu::VarType(glu::TYPE_UINT_VEC2, glu::PRECISION_HIGHP)));
214e5c31af7Sopenharmony_ci	}
215e5c31af7Sopenharmony_ci
216e5c31af7Sopenharmony_ciprivate:
217e5c31af7Sopenharmony_ci	ShaderClockCase				(const ShaderClockCase&);
218e5c31af7Sopenharmony_ci	ShaderClockCase& operator=	(const ShaderClockCase&);
219e5c31af7Sopenharmony_ci
220e5c31af7Sopenharmony_ci	testType							m_operation;
221e5c31af7Sopenharmony_ci	ShaderSpec							m_shaderSpec;
222e5c31af7Sopenharmony_ci	glu::ShaderType						m_shaderType;
223e5c31af7Sopenharmony_ci};
224e5c31af7Sopenharmony_ci
225e5c31af7Sopenharmony_civoid addShaderClockTests (tcu::TestCaseGroup* testGroup)
226e5c31af7Sopenharmony_ci{
227e5c31af7Sopenharmony_ci	static glu::ShaderType stages[] =
228e5c31af7Sopenharmony_ci	{
229e5c31af7Sopenharmony_ci		glu::SHADERTYPE_VERTEX,
230e5c31af7Sopenharmony_ci		glu::SHADERTYPE_FRAGMENT,
231e5c31af7Sopenharmony_ci		glu::SHADERTYPE_COMPUTE
232e5c31af7Sopenharmony_ci	};
233e5c31af7Sopenharmony_ci
234e5c31af7Sopenharmony_ci	static testType operations[] =
235e5c31af7Sopenharmony_ci    {
236e5c31af7Sopenharmony_ci		{SUBGROUP, BIT_64, "clockARB"},
237e5c31af7Sopenharmony_ci		{SUBGROUP, BIT_32, "clock2x32ARB" },
238e5c31af7Sopenharmony_ci		{DEVICE,   BIT_64, "clockRealtimeEXT"},
239e5c31af7Sopenharmony_ci		{DEVICE,   BIT_32, "clockRealtime2x32EXT"}
240e5c31af7Sopenharmony_ci	};
241e5c31af7Sopenharmony_ci
242e5c31af7Sopenharmony_ci	tcu::TestContext& testCtx = testGroup->getTestContext();
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ci	for (size_t i = 0; i != DE_LENGTH_OF_ARRAY(stages); ++i)
245e5c31af7Sopenharmony_ci	{
246e5c31af7Sopenharmony_ci		const char* stageName = (stages[i] == glu::SHADERTYPE_VERTEX) ? ("vertex")
247e5c31af7Sopenharmony_ci								: (stages[i] == glu::SHADERTYPE_FRAGMENT) ? ("fragment")
248e5c31af7Sopenharmony_ci								: (stages[i] == glu::SHADERTYPE_COMPUTE) ? ("compute")
249e5c31af7Sopenharmony_ci								: (DE_NULL);
250e5c31af7Sopenharmony_ci
251e5c31af7Sopenharmony_ci		const std::string setName = std::string() + stageName;
252e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> stageGroupTest(new tcu::TestCaseGroup(testCtx, setName.c_str()));
253e5c31af7Sopenharmony_ci
254e5c31af7Sopenharmony_ci		for (size_t j = 0; j != DE_LENGTH_OF_ARRAY(operations); ++j)
255e5c31af7Sopenharmony_ci		{
256e5c31af7Sopenharmony_ci			stageGroupTest->addChild(new ShaderClockCase(testCtx, operations[j], stages[i]));
257e5c31af7Sopenharmony_ci		}
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_ci		testGroup->addChild(stageGroupTest.release());
260e5c31af7Sopenharmony_ci	}
261e5c31af7Sopenharmony_ci}
262e5c31af7Sopenharmony_ci
263e5c31af7Sopenharmony_ci} // anonymous
264e5c31af7Sopenharmony_ci
265e5c31af7Sopenharmony_citcu::TestCaseGroup* createShaderClockTests(tcu::TestContext& testCtx)
266e5c31af7Sopenharmony_ci{
267e5c31af7Sopenharmony_ci	return createTestGroup(testCtx, "shader_clock", addShaderClockTests);
268e5c31af7Sopenharmony_ci}
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci} // shaderexecutor
271e5c31af7Sopenharmony_ci} // vkt
272