1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 LunarG, Inc.
6  * Copyright (c) 2023 Nintendo
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 Shader Object Performance Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktShaderObjectPerformanceTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkShaderObjectUtil.hpp"
30 #include "vktShaderObjectCreateUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include <chrono>
37 
38 namespace vkt
39 {
40 namespace ShaderObject
41 {
42 
43 namespace
44 {
45 
46 enum TestType {
47 	DRAW_STATIC_PIPELINE,
48 	DRAW_DYNAMIC_PIPELINE,
49 	DRAW_LINKED_SHADERS,
50 	DRAW_BINARY,
51 	DRAW_BINARY_BIND,
52 };
53 
54 enum BinaryType {
55 	BINARY_SHADER_CREATE,
56 	BINARY_MEMCPY,
57 };
58 
59 enum DrawType {
60 	DRAW,
61 	DRAW_INDEXED,
62 	DRAW_INDEXED_INDIRECT,
63 	DRAW_INDEXED_INDIRECT_COUNT,
64 	DRAW_INDIRECT,
65 	DRAW_INDIRECT_COUNT,
66 };
67 
68 enum DispatchType {
69 	DISPATCH,
70 	DISPATCH_BASE,
71 	DISPATCH_INDIRECT,
72 };
73 
74 class ShaderObjectPerformanceInstance : public vkt::TestInstance
75 {
76 public:
ShaderObjectPerformanceInstance(Context& context, const DrawType drawType, const TestType& type)77 								ShaderObjectPerformanceInstance		(Context& context, const DrawType drawType, const TestType& type)
78 																	: vkt::TestInstance	(context)
79 																	, m_drawType		(drawType)
80 																	, m_type			(type)
81 																	{}
~ShaderObjectPerformanceInstance(void)82 	virtual						~ShaderObjectPerformanceInstance	(void) {}
83 
84 	tcu::TestStatus				iterate								(void) override;
85 private:
86 	std::chrono::nanoseconds	draw								(const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indexBuffer, vk::VkBuffer indirectBuffer, vk::VkBuffer countBuffer) const;
87 
88 	const DrawType	m_drawType;
89 	const TestType	m_type;
90 };
91 
extensionEnabled(const std::vector<std::string>& deviceExtensions, const std::string& ext)92 bool extensionEnabled(const std::vector<std::string>& deviceExtensions, const std::string& ext)
93 {
94 	return std::find(deviceExtensions.begin(), deviceExtensions.end(), ext) != deviceExtensions.end();
95 }
96 
getDynamicStates(Context& context)97 std::vector<vk::VkDynamicState> getDynamicStates (Context& context)
98 {
99 	const auto deviceExtensions		= vk::removeUnsupportedShaderObjectExtensions(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceExtensions());
100 	const auto& edsFeatures			= context.getExtendedDynamicStateFeaturesEXT();
101 	const auto& eds2Features		= context.getExtendedDynamicState2FeaturesEXT();
102 	const auto& eds3Features		= context.getExtendedDynamicState3FeaturesEXT();
103 	const auto& viFeatures			= context.getVertexInputDynamicStateFeaturesEXT();
104 
105 	std::vector<vk::VkDynamicState> dynamicStates = {
106 		vk::VK_DYNAMIC_STATE_LINE_WIDTH,
107 		vk::VK_DYNAMIC_STATE_DEPTH_BIAS,
108 		vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS,
109 		vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS,
110 		vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
111 		vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
112 		vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE,
113 	};
114 
115 	if (edsFeatures.extendedDynamicState)
116 	{
117 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CULL_MODE_EXT);
118 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT);
119 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
120 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
121 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
122 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
123 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
124 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
125 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT);
126 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT);
127 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
128 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT);
129 	}
130 	else
131 	{
132 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT);
133 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR);
134 	}
135 	if (eds2Features.extendedDynamicState2)
136 	{
137 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE);
138 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
139 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE);
140 	}
141 	if (eds2Features.extendedDynamicState2LogicOp)
142 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT);
143 	if (eds2Features.extendedDynamicState2PatchControlPoints)
144 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
145 
146 	if (eds3Features.extendedDynamicState3TessellationDomainOrigin)
147 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT);
148 	if (eds3Features.extendedDynamicState3DepthClampEnable)
149 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT);
150 	if (eds3Features.extendedDynamicState3PolygonMode)
151 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT);
152 	if (eds3Features.extendedDynamicState3RasterizationSamples)
153 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
154 	if (eds3Features.extendedDynamicState3SampleMask)
155 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
156 	if (eds3Features.extendedDynamicState3AlphaToCoverageEnable)
157 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
158 	if (eds3Features.extendedDynamicState3AlphaToOneEnable)
159 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
160 	if (eds3Features.extendedDynamicState3LogicOpEnable)
161 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
162 	if (eds3Features.extendedDynamicState3ColorBlendEnable)
163 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
164 	if (eds3Features.extendedDynamicState3ColorBlendEquation)
165 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
166 	if (eds3Features.extendedDynamicState3ColorWriteMask)
167 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
168 	if (viFeatures.vertexInputDynamicState)
169 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
170 
171 	if (extensionEnabled(deviceExtensions, "VK_EXT_transform_feedback") && eds3Features.extendedDynamicState3RasterizationStream)
172 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
173 	if (extensionEnabled(deviceExtensions, "VK_EXT_blend_operation_advanced") && eds3Features.extendedDynamicState3ColorBlendAdvanced)
174 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
175 	if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization") && eds3Features.extendedDynamicState3ConservativeRasterizationMode)
176 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
177 	if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") && eds3Features.extendedDynamicState3CoverageModulationMode)
178 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV);
179 	if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") && eds3Features.extendedDynamicState3CoverageModulationTableEnable)
180 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV);
181 	if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") && eds3Features.extendedDynamicState3CoverageModulationTable)
182 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV);
183 	if (extensionEnabled(deviceExtensions, "VK_NV_coverage_reduction_mode") && eds3Features.extendedDynamicState3CoverageReductionMode)
184 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
185 	if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color") && eds3Features.extendedDynamicState3CoverageToColorEnable)
186 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV);
187 	if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color") && eds3Features.extendedDynamicState3CoverageToColorLocation)
188 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV);
189 	if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_enable") && eds3Features.extendedDynamicState3DepthClipEnable)
190 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT);
191 	if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_control") && eds3Features.extendedDynamicState3DepthClipNegativeOneToOne)
192 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT);
193 	if (extensionEnabled(deviceExtensions, "VK_EXT_color_write_enable"))
194 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
195 	if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization") && eds3Features.extendedDynamicState3ExtraPrimitiveOverestimationSize)
196 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
197 	if (extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization") && eds3Features.extendedDynamicState3LineRasterizationMode)
198 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
199 	if (extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization") && eds3Features.extendedDynamicState3LineStippleEnable)
200 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
201 	if (extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization"))
202 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
203 	if (extensionEnabled(deviceExtensions, "VK_EXT_provoking_vertex") && eds3Features.extendedDynamicState3ProvokingVertexMode)
204 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
205 	if (extensionEnabled(deviceExtensions, "VK_KHR_fragment_shading_rate"))
206 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR);
207 	if (extensionEnabled(deviceExtensions, "VK_NV_representative_fragment_test") && eds3Features.extendedDynamicState3RepresentativeFragmentTestEnable)
208 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV);
209 	if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations") && eds3Features.extendedDynamicState3SampleLocationsEnable)
210 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
211 	if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations"))
212 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
213 	if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image") && eds3Features.extendedDynamicState3ShadingRateImageEnable)
214 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
215 	if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
216 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV);
217 	if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
218 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV);
219 	if (extensionEnabled(deviceExtensions, "VK_NV_viewport_swizzle") && eds3Features.extendedDynamicState3ViewportSwizzle)
220 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV);
221 	if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling") && eds3Features.extendedDynamicState3ViewportWScalingEnable)
222 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV);
223 	if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling"))
224 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV);
225 	if (extensionEnabled(deviceExtensions, "VK_NV_scissor_exclusive"))
226 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV);
227 	if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
228 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
229 	if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
230 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
231 	if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
232 		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT);
233 
234 	return dynamicStates;
235 }
236 
createShaderFromBinary(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::Move<vk::VkShaderEXT>& shader, vk::VkShaderStageFlagBits stage)237 vk::VkShaderEXT createShaderFromBinary (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::Move<vk::VkShaderEXT>& shader, vk::VkShaderStageFlagBits stage)
238 {
239 	size_t						dataSize = 0;
240 	vk.getShaderBinaryDataEXT(device, *shader, &dataSize, DE_NULL);
241 	std::vector<deUint8>		data(dataSize);
242 	vk.getShaderBinaryDataEXT(device, *shader, &dataSize, data.data());
243 
244 	const vk::VkShaderCreateInfoEXT binaryShaderCreateInfo =
245 	{
246 		vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
247 		DE_NULL,										// const void*					pNext;
248 		0u,												// VkShaderCreateFlagsEXT		flags;
249 		stage,											// VkShaderStageFlagBits		stage;
250 		0u,												// VkShaderStageFlags			nextStage;
251 		vk::VK_SHADER_CODE_TYPE_BINARY_EXT,				// VkShaderCodeTypeEXT			codeType;
252 		dataSize,										// size_t						codeSize;
253 		data.data(),									// const void*					pCode;
254 		"main",											// const char*					pName;
255 		0u,												// uint32_t						setLayoutCount;
256 		DE_NULL,										// VkDescriptorSetLayout*		pSetLayouts;
257 		0u,												// uint32_t						pushConstantRangeCount;
258 		DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
259 		DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
260 	};
261 
262 	vk::VkShaderEXT binaryShader;
263 	vk.createShadersEXT(device, 1, &binaryShaderCreateInfo, DE_NULL, &binaryShader);
264 	return binaryShader;
265 }
266 
draw(const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indexBuffer, vk::VkBuffer indirectBuffer, vk::VkBuffer countBuffer) const267 std::chrono::nanoseconds ShaderObjectPerformanceInstance::draw (const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indexBuffer, vk::VkBuffer indirectBuffer, vk::VkBuffer countBuffer) const
268 {
269 	if (m_drawType == DRAW)
270 	{
271 		const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
272 		vk.cmdDraw(cmdBuffer, 4, 1, 0, 0);
273 		return std::chrono::high_resolution_clock::now() - shaderObjectStart;
274 	}
275 	else if (m_drawType == DRAW_INDEXED)
276 	{
277 		vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0u, vk::VK_INDEX_TYPE_UINT16);
278 		const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
279 		vk.cmdDrawIndexed(cmdBuffer, 4, 1, 0, 0, 0);
280 		return std::chrono::high_resolution_clock::now() - shaderObjectStart;
281 	}
282 	else if (m_drawType == DRAW_INDEXED_INDIRECT)
283 	{
284 		vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0u, vk::VK_INDEX_TYPE_UINT16);
285 		const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
286 		vk.cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer, 0u, 1u, sizeof(vk::VkDrawIndexedIndirectCommand));
287 		return std::chrono::high_resolution_clock::now() - shaderObjectStart;
288 	}
289 	else if (m_drawType == DRAW_INDEXED_INDIRECT_COUNT)
290 	{
291 		vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0u, vk::VK_INDEX_TYPE_UINT16);
292 		const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
293 		vk.cmdDrawIndexedIndirectCount(cmdBuffer, indirectBuffer, 0u, countBuffer, 0u, 1u, sizeof(vk::VkDrawIndexedIndirectCommand));
294 		return std::chrono::high_resolution_clock::now() - shaderObjectStart;
295 	}
296 	else if (m_drawType == DRAW_INDIRECT)
297 	{
298 		const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
299 		vk.cmdDrawIndirect(cmdBuffer, indirectBuffer, 0u, 1u, sizeof(vk::VkDrawIndirectCommand));
300 		return std::chrono::high_resolution_clock::now() - shaderObjectStart;
301 	}
302 	else if (m_drawType == DRAW_INDIRECT_COUNT)
303 	{
304 		const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
305 		vk.cmdDrawIndirectCount(cmdBuffer, indirectBuffer, 0u, countBuffer, 0u, 1u, sizeof(vk::VkDrawIndirectCommand));
306 		return std::chrono::high_resolution_clock::now() - shaderObjectStart;
307 	}
308 	return std::chrono::nanoseconds(0);
309 }
310 
iterate(void)311 tcu::TestStatus ShaderObjectPerformanceInstance::iterate (void)
312 {
313 	const vk::VkInstance				instance					= m_context.getInstance();
314 	const vk::InstanceDriver			instanceDriver				(m_context.getPlatformInterface(), instance);
315 	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
316 	const vk::VkDevice					device						= m_context.getDevice();
317 	const vk::VkQueue					queue						= m_context.getUniversalQueue();
318 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
319 	auto&								alloc						= m_context.getDefaultAllocator();
320 	const auto							deviceExtensions			= vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
321 	const bool							tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
322 	const bool							geometrySupported			= m_context.getDeviceFeatures().geometryShader;
323 	const bool							taskSupported				= m_context.getMeshShaderFeatures().taskShader;
324 	const bool							meshSupported				= m_context.getMeshShaderFeatures().meshShader;
325 
326 	vk::VkFormat						colorAttachmentFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
327 	const auto							subresourceRange			= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
328 
329 	const vk::Move<vk::VkCommandPool>	cmdPool						(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
330 	const vk::Move<vk::VkCommandBuffer>	cmdBuffer					(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
331 
332 	const vk::VkPrimitiveTopology		topology					= tessellationSupported ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
333 
334 	const deUint32						geomIndex					= tessellationSupported ? 4u : 2u;
335 
336 	const vk::VkImageCreateInfo	createInfo =
337 	{
338 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
339 		DE_NULL,									// const void*				pNext
340 		0u,											// VkImageCreateFlags		flags
341 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
342 		colorAttachmentFormat,						// VkFormat					format
343 		{ 32, 32, 1 },								// VkExtent3D				extent
344 		1u,											// uint32_t					mipLevels
345 		1u,											// uint32_t					arrayLayers
346 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
347 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
348 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
349 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
350 		0,											// uint32_t					queueFamilyIndexCount
351 		DE_NULL,									// const uint32_t*			pQueueFamilyIndices
352 		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
353 	};
354 
355 	de::MovePtr<vk::ImageWithMemory>	image					= de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
356 	const auto							imageView				= vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
357 	const vk::VkRect2D					renderArea				= vk::makeRect2D(0, 0, 32, 32);
358 
359 	const vk::VkDeviceSize				colorOutputBufferSize	= renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
360 	de::MovePtr<vk::BufferWithMemory>	colorOutputBuffer		= de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
361 		vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
362 
363 	const auto&		binaries	= m_context.getBinaryCollection();
364 
365 	std::vector<vk::VkShaderCreateInfoEXT> createInfos =
366 	{
367 		vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, binaries.get("vert"), tessellationSupported, geometrySupported),
368 		vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("frag"), tessellationSupported, geometrySupported),
369 	};
370 
371 	if (tessellationSupported)
372 	{
373 		createInfos.push_back(vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, binaries.get("tesc"), tessellationSupported, geometrySupported));
374 		createInfos.push_back(vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, binaries.get("tese"), tessellationSupported, geometrySupported));
375 	}
376 	if (geometrySupported)
377 	{
378 		createInfos.push_back(vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, binaries.get("geom"), tessellationSupported, geometrySupported));
379 	}
380 
381 	if (tessellationSupported)
382 	{
383 		createInfos[0].nextStage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
384 		createInfos[2].nextStage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
385 		if (geometrySupported)
386 			createInfos[3].nextStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
387 		else
388 			createInfos[3].nextStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
389 	}
390 	else if (geometrySupported)
391 	{
392 		createInfos[0].nextStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
393 		createInfos[geomIndex].nextStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
394 	}
395 	else
396 	{
397 		createInfos[0].nextStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
398 	}
399 
400 	vk::Move<vk::VkShaderEXT>		vertShader		 = vk::createShader(vk, device, createInfos[0]);
401 	vk::Move<vk::VkShaderEXT>		fragShader		 = vk::createShader(vk, device, createInfos[1]);
402 	vk::Move<vk::VkShaderEXT>		tescShader;
403 	vk::Move<vk::VkShaderEXT>		teseShader;
404 	vk::Move<vk::VkShaderEXT>		geomShader;
405 
406 	if (tessellationSupported)
407 	{
408 		tescShader = vk::createShader(vk, device, createInfos[2]);
409 		teseShader = vk::createShader(vk, device, createInfos[3]);
410 	}
411 	if (geometrySupported)
412 	{
413 		geomShader = vk::createShader(vk, device, createInfos[geomIndex]);
414 	}
415 
416 	std::vector<vk::VkShaderEXT> refShaders;
417 
418 	if (m_type == DRAW_LINKED_SHADERS)
419 	{
420 		refShaders.resize(5, VK_NULL_HANDLE);
421 		for (auto& info : createInfos)
422 			info.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
423 
424 		vk.createShadersEXT(device, (deUint32)createInfos.size(), createInfos.data(), DE_NULL, refShaders.data());
425 	}
426 	else if (m_type == DRAW_BINARY || m_type == DRAW_BINARY_BIND)
427 	{
428 		refShaders.resize(5, VK_NULL_HANDLE);
429 		refShaders[0] = createShaderFromBinary(vk, device, vertShader, vk::VK_SHADER_STAGE_VERTEX_BIT);
430 		refShaders[1] = createShaderFromBinary(vk, device, fragShader, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
431 		if (tessellationSupported)
432 		{
433 			refShaders[2] = createShaderFromBinary(vk, device, tescShader, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
434 			refShaders[3] = createShaderFromBinary(vk, device, teseShader, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
435 		}
436 		if (geometrySupported)
437 		{
438 			refShaders[geomIndex] = createShaderFromBinary(vk, device, geomShader, vk::VK_SHADER_STAGE_GEOMETRY_BIT);
439 		}
440 	}
441 
442 	vk::VkShaderEXT linkedShaders[5];
443 	vk.createShadersEXT(device, static_cast<uint32_t>(createInfos.size()), createInfos.data(), nullptr, linkedShaders);
444 
445 	vk::Move<vk::VkShaderEXT>		linkedVertShader = vk::Move<vk::VkShaderEXT>(vk::check<vk::VkShaderEXT>(linkedShaders[0]), vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
446 	vk::Move<vk::VkShaderEXT>		linkedFragShader = vk::Move<vk::VkShaderEXT>(vk::check<vk::VkShaderEXT>(linkedShaders[1]), vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
447 	vk::Move<vk::VkShaderEXT>		linkedTescShader;
448 	vk::Move<vk::VkShaderEXT>		linkedTeseShader;
449 	vk::Move<vk::VkShaderEXT>		linkedGeomShader;
450 	if (tessellationSupported)
451 	{
452 		linkedTescShader = vk::Move<vk::VkShaderEXT>(vk::check<vk::VkShaderEXT>(linkedShaders[2]), vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
453 		linkedTeseShader = vk::Move<vk::VkShaderEXT>(vk::check<vk::VkShaderEXT>(linkedShaders[3]), vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
454 	}
455 	if (geometrySupported)
456 	{
457 		linkedGeomShader = vk::Move<vk::VkShaderEXT>(vk::check<vk::VkShaderEXT>(linkedShaders[geomIndex]), vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
458 	}
459 
460 	vk::Move<vk::VkShaderModule>		vertShaderModule = createShaderModule(vk, device, binaries.get("vert"));
461 	vk::Move<vk::VkShaderModule>		fragShaderModule = createShaderModule(vk, device, binaries.get("frag"));
462 	vk::Move<vk::VkShaderModule>		dummyVertShaderModule = createShaderModule(vk, device, binaries.get("dummyVert"));
463 	vk::Move<vk::VkShaderModule>		dummyFragShaderModule = createShaderModule(vk, device, binaries.get("dummyFrag"));
464 	vk::Move<vk::VkShaderModule>		tescShaderModule;
465 	vk::Move<vk::VkShaderModule>		teseShaderModule;
466 	vk::Move<vk::VkShaderModule>		geomShaderModule;
467 	if (tessellationSupported)
468 	{
469 		tescShaderModule = createShaderModule(vk, device, binaries.get("tesc"));
470 		teseShaderModule = createShaderModule(vk, device, binaries.get("tese"));
471 	}
472 	if (geometrySupported)
473 	{
474 		geomShaderModule = createShaderModule(vk, device, binaries.get("geom"));
475 	}
476 
477 	const auto		emptyPipelineLayout = makePipelineLayout(vk, device);
478 
479 	const vk::VkPipelineVertexInputStateCreateInfo		vertexInputStateParams =
480 	{
481 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
482 		DE_NULL,														// const void*								pNext;
483 		0u,																// VkPipelineVertexInputStateCreateFlags	flags;
484 		0u,																// deUint32									vertexBindingDescriptionCount;
485 		DE_NULL,														// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
486 		0u,																// deUint32									vertexAttributeDescriptionCount;
487 		DE_NULL															// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
488 	};
489 
490 	const vk::VkPipelineTessellationStateCreateInfo		tessStateCreateInfo =
491 	{
492 		vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
493 		DE_NULL,														//	const void*								pNext;
494 		0u,																//	VkPipelineTessellationStateCreateFlags	flags;
495 		4u,																//	uint32_t								patchControlPoints;
496 	};
497 
498 	vk::VkPipelineInputAssemblyStateCreateInfo			pipelineInputAssemblyStateInfo =
499 	{
500 		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
501 		DE_NULL,															// const void*                                 pNext;
502 		(vk::VkPipelineInputAssemblyStateCreateFlags)0u,					// VkPipelineInputAssemblyStateCreateFlags     flags;
503 		topology,															// VkPrimitiveTopology                         topology;
504 		VK_FALSE,															// VkBool32                                    primitiveRestartEnable;
505 	};
506 
507 	vk::VkPipelineRenderingCreateInfo					pipelineRenderingCreateInfo =
508 	{
509 		vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,	// VkStructureType	sType
510 		DE_NULL,												// const void*		pNext
511 		0u,														// uint32_t			viewMask
512 		1u,														// uint32_t			colorAttachmentCount
513 		&colorAttachmentFormat,									// const VkFormat*	pColorAttachmentFormats
514 		vk::VK_FORMAT_UNDEFINED,								// VkFormat			depthAttachmentFormat
515 		vk::VK_FORMAT_UNDEFINED,								// VkFormat			stencilAttachmentFormat
516 	};
517 
518 	const vk::VkViewport								viewport	= vk::makeViewport((float)renderArea.extent.width, 0.0f, (float)renderArea.extent.width, (float)renderArea.extent.height, 0.0f, 1.0f);
519 	const vk::VkRect2D									scissor		= vk::makeRect2D(renderArea.extent);
520 
521 	vk::VkPipelineViewportStateCreateInfo				viewportStateCreateInfo =
522 	{
523 		vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType
524 		DE_NULL,													// const void*                                 pNext
525 		(vk::VkPipelineViewportStateCreateFlags)0u,					// VkPipelineViewportStateCreateFlags          flags
526 		(m_type == DRAW_DYNAMIC_PIPELINE) ? 0u : 1u,				// deUint32                                    viewportCount
527 		&viewport,													// const VkViewport*                           pViewports
528 		(m_type == DRAW_DYNAMIC_PIPELINE) ? 0u : 1u,				// deUint32                                    scissorCount
529 		&scissor													// const VkRect2D*                             pScissors
530 	};
531 
532 	const auto												dynamicStates			= getDynamicStates(m_context);
533 
534 	const vk::VkPipelineDynamicStateCreateInfo				dynamicStateCreateInfo	=
535 	{
536 		vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
537 		DE_NULL,													//	const void*							pNext;
538 		(vk::VkPipelineDynamicStateCreateFlags)0u,					//	VkPipelineDynamicStateCreateFlags	flags;
539 		static_cast<deUint32>(dynamicStates.size()),				//	deUint32							dynamicStateCount;
540 		dynamicStates.data(),										//	const VkDynamicState*				pDynamicStates;
541 	};
542 
543 	const vk::VkPipelineDynamicStateCreateInfo*				pDynamicStateCreateInfo = (m_type == DRAW_DYNAMIC_PIPELINE) ? &dynamicStateCreateInfo : DE_NULL;
544 
545 	const auto							pipeline			= makeGraphicsPipeline(vk, device, emptyPipelineLayout.get(), vertShaderModule.get(), tescShaderModule.get(), teseShaderModule.get(), geomShaderModule.get(), fragShaderModule.get(), VK_NULL_HANDLE, 0u, &vertexInputStateParams, &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL, DE_NULL, pDynamicStateCreateInfo, &pipelineRenderingCreateInfo);
546 	pipelineInputAssemblyStateInfo.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
547 	viewportStateCreateInfo.viewportCount = 1u;
548 	viewportStateCreateInfo.scissorCount = 1u;
549 	const auto							dummyPipeline		= makeGraphicsPipeline(vk, device, emptyPipelineLayout.get(), dummyVertShaderModule.get(), VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, dummyFragShaderModule.get(), VK_NULL_HANDLE, 0u, &vertexInputStateParams, &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, &pipelineRenderingCreateInfo);
550 
551 	const vk::VkClearValue				clearValue			= vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
552 
553 	vk::BufferWithMemory				indirectBuffer		(vk, device, alloc, vk::makeBufferCreateInfo(sizeof(vk::VkDrawIndirectCommand) + sizeof(vk::VkDrawIndexedIndirectCommand), vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
554 
555 	if (m_drawType == DRAW_INDEXED_INDIRECT || m_drawType == DRAW_INDEXED_INDIRECT_COUNT)
556 	{
557 		vk::VkDrawIndexedIndirectCommand* indirectDataPtr = reinterpret_cast<vk::VkDrawIndexedIndirectCommand*>(indirectBuffer.getAllocation().getHostPtr());
558 		indirectDataPtr->indexCount = 4;
559 		indirectDataPtr->instanceCount = 1;
560 		indirectDataPtr->firstIndex = 0;
561 		indirectDataPtr->vertexOffset = 0;
562 		indirectDataPtr->firstInstance = 0;
563 	}
564 	else
565 	{
566 		vk::VkDrawIndirectCommand*		indirectDataPtr = reinterpret_cast<vk::VkDrawIndirectCommand*>(indirectBuffer.getAllocation().getHostPtr());
567 		indirectDataPtr->vertexCount = 4;
568 		indirectDataPtr->instanceCount = 1;
569 		indirectDataPtr->firstVertex = 0;
570 		indirectDataPtr->firstInstance = 0;
571 	}
572 
573 	vk::BufferWithMemory				countBuffer			(vk, device, alloc, vk::makeBufferCreateInfo(sizeof(deUint32), vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
574 	deUint32*							countDataPtr		= reinterpret_cast<deUint32*>(countBuffer.getAllocation().getHostPtr());
575 	countDataPtr[0] = 1u;
576 
577 	vk::BufferWithMemory				indexBuffer			(vk, device, alloc, vk::makeBufferCreateInfo(sizeof(deUint32) * 4, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
578 	deUint32*							indexDataPtr		= reinterpret_cast<deUint32*>(indexBuffer.getAllocation().getHostPtr());
579 	indexDataPtr[0] = 0u;
580 	indexDataPtr[1] = 1u;
581 	indexDataPtr[2] = 2u;
582 	indexDataPtr[3] = 3u;
583 
584 	const vk::VkDeviceSize				bufferSize			= 64;
585 	de::MovePtr<vk::BufferWithMemory>	buffer				= de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(vk, device, alloc, vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), vk::MemoryRequirement::HostVisible));
586 
587 	// Do a dummy run, to ensure memory allocations are done with before performance testing
588 	{
589 		vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
590 		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *dummyPipeline);
591 		vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
592 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
593 		vk::endRendering(vk, *cmdBuffer);
594 		vk::endCommandBuffer(vk, *cmdBuffer);
595 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
596 	}
597 
598 	std::chrono::nanoseconds			time				= std::chrono::nanoseconds(0);
599 	std::chrono::nanoseconds			refTime				= std::chrono::nanoseconds(0);
600 	std::chrono::nanoseconds			maxTime				= std::chrono::nanoseconds(0);
601 	std::chrono::nanoseconds			maxRefTime			= std::chrono::nanoseconds(0);
602 
603 	for (deUint32 i = 0; i < 100; ++i)
604 	{
605 		std::chrono::nanoseconds	currentTime;
606 		std::chrono::nanoseconds	currentRefTime;
607 
608 		if (m_type == DRAW_BINARY_BIND)
609 		{
610 			vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
611 			const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
612 			vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader, taskSupported, meshSupported);
613 			currentTime = std::chrono::high_resolution_clock::now() - shaderObjectStart;
614 			vk::endCommandBuffer(vk, *cmdBuffer);
615 
616 			vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
617 			const auto refShaderObjectStart = std::chrono::high_resolution_clock::now();
618 			vk::bindGraphicsShaders(vk, *cmdBuffer, refShaders[0], refShaders[2], refShaders[3], refShaders[4], refShaders[1], taskSupported, meshSupported);
619 			currentRefTime = std::chrono::high_resolution_clock::now() - refShaderObjectStart;
620 			vk::endCommandBuffer(vk, *cmdBuffer);
621 		}
622 		else
623 		{
624 			vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
625 			vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader, taskSupported, meshSupported);
626 			vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, topology, false, !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
627 			vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
628 			currentTime = draw(vk, *cmdBuffer, *indexBuffer, *indirectBuffer, *countBuffer);
629 			vk::endRendering(vk, *cmdBuffer);
630 			vk::endCommandBuffer(vk, *cmdBuffer);
631 			submitCommandsAndWait(vk, device, queue, *cmdBuffer);
632 
633 			if (m_type == DRAW_LINKED_SHADERS || m_type == DRAW_BINARY)
634 			{
635 				vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
636 				vk::bindGraphicsShaders(vk, *cmdBuffer, refShaders[0], refShaders[2], refShaders[3], refShaders[4], refShaders[1], taskSupported, meshSupported);
637 				vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, topology, false, !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
638 				vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
639 				currentRefTime = draw(vk, *cmdBuffer, *indexBuffer, *indirectBuffer, *countBuffer);
640 				vk::endRendering(vk, *cmdBuffer);
641 				vk::endCommandBuffer(vk, *cmdBuffer);
642 				submitCommandsAndWait(vk, device, queue, *cmdBuffer);
643 			}
644 			else
645 			{
646 				vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
647 				vk::VkDeviceSize offset = 0u;
648 				vk::VkDeviceSize stride = 16u;
649 				vk.cmdBindVertexBuffers2(*cmdBuffer, 0u, 1u, &**buffer, &offset, &bufferSize, &stride);
650 				vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, topology, false, !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
651 				vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
652 				vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
653 				currentRefTime = draw(vk, *cmdBuffer, *indexBuffer, *indirectBuffer, *countBuffer);
654 				vk::endRendering(vk, *cmdBuffer);
655 				vk::endCommandBuffer(vk, *cmdBuffer);
656 				submitCommandsAndWait(vk, device, queue, *cmdBuffer);
657 			}
658 		}
659 
660 		time += currentTime;
661 		if (currentTime > maxTime)
662 			maxTime = currentTime;
663 
664 		refTime += currentRefTime;
665 		if (currentRefTime > maxRefTime)
666 			maxRefTime = currentRefTime;
667 	}
668 
669 	for (const auto& shader : refShaders)
670 		vk.destroyShaderEXT(device, shader, DE_NULL);
671 
672 	if (m_type == DRAW_STATIC_PIPELINE)
673 	{
674 		if (maxTime > maxRefTime * 1.5f)
675 			return tcu::TestStatus::fail("Maximum shader object rendering iteration was more than 50% slower than maximum static pipeline iteration rendering");
676 		if (time > refTime * 1.25f)
677 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Shader object rendering was more than 25% slower than static pipeline rendering");
678 		if (maxTime > maxRefTime * 1.25f)
679 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Maximum shader object iteration rendering was more than 25% slower than maximum static pipeline iteration rendering");
680 	}
681 	else if (m_type == DRAW_DYNAMIC_PIPELINE)
682 	{
683 		if (maxTime > maxRefTime * 1.2f)
684 			return tcu::TestStatus::fail("Maximum shader object iteration rendering was more than 20% slower than maximum dynamic pipeline iteration rendering");
685 		if (time > refTime * 1.1f)
686 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Shader object rendering was more than 10% slower than dynamic pipeline rendering");
687 		if (maxTime > maxRefTime * 1.1f)
688 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Maximum shader object iteration rendering was more than 10% slower than maximum dynamic pipeline iteration rendering");
689 	}
690 	else if (m_type == DRAW_LINKED_SHADERS)
691 	{
692 		if (maxTime > maxRefTime * 1.05f)
693 			return tcu::TestStatus::fail("Maximum unlinked shader object iteration rendering was more than 5% slower than maximum linked shader object iteration rendering");
694 		if (time * 1.05f < refTime)
695 			return tcu::TestStatus::fail("Linked shader object rendering was more than 5% slower than unlinked shader object rendering");
696 		if (maxTime * 1.05f < maxRefTime)
697 			return tcu::TestStatus::fail("Maximum linked shader object iteration rendering was more than 5% slower than maximum unlinked shader object iteratino rendering");
698 	}
699 	else if (m_type == DRAW_BINARY)
700 	{
701 		if (maxTime > maxRefTime * 1.05f)
702 			return tcu::TestStatus::fail("Maximum shader object iteration rendering was more than 5% slower than maximum binary shader object iteration rendering");
703 		if (time * 1.05f < refTime)
704 			return tcu::TestStatus::fail("Binary shader object rendering was more than 5% slower than shader object rendering");
705 		if (maxTime * 1.05f < maxRefTime)
706 			return tcu::TestStatus::fail("Maximum binary shader object iteration rendering was more than 5% slower than maximum shader object iteration rendering");
707 	}
708 	else if (m_type == DRAW_BINARY_BIND)
709 	{
710 		if (maxTime > maxRefTime * 1.05f)
711 			return tcu::TestStatus::fail("Maximum shader object iteration binding was more than 5% slower than maximum binary shader object iteration binding");
712 		if (time * 1.05f < refTime)
713 			return tcu::TestStatus::fail("Binary shader object binding was more than 5% slower than shader object binding");
714 		if (maxTime * 1.05f < maxRefTime)
715 			return tcu::TestStatus::fail("Maximum binary shader object iteration binding was more than 5% slower than maximum shader object iteration binding");
716 	}
717 
718 	return tcu::TestStatus::pass("Pass");
719 }
720 
721 class ShaderObjectPerformanceCase : public vkt::TestCase
722 {
723 public:
ShaderObjectPerformanceCase(tcu::TestContext& testCtx, const std::string& name, const DrawType drawType, const TestType& type)724 	ShaderObjectPerformanceCase(tcu::TestContext& testCtx, const std::string& name, const DrawType drawType, const TestType& type)
725 		: vkt::TestCase	(testCtx, name)
726 		, m_drawType	(drawType)
727 		, m_type		(type)
728 	{}
~ShaderObjectPerformanceCase(void)729 	virtual			~ShaderObjectPerformanceCase(void) {}
730 
731 	void			checkSupport(vkt::Context& context) const override;
732 	virtual void	initPrograms(vk::SourceCollections& programCollection) const override;
733 	TestInstance*	createInstance(Context& context) const override { return new ShaderObjectPerformanceInstance(context, m_drawType, m_type); }
734 
735 private:
736 	DrawType	m_drawType;
737 	TestType	m_type;
738 };
739 
checkSupport(Context& context) const740 void ShaderObjectPerformanceCase::checkSupport(Context& context) const
741 {
742 	context.requireDeviceFunctionality("VK_EXT_shader_object");
743 }
744 
initPrograms(vk::SourceCollections& programCollection) const745 void ShaderObjectPerformanceCase::initPrograms(vk::SourceCollections& programCollection) const
746 {
747 	vk::addBasicShaderObjectShaders(programCollection);
748 
749 	std::stringstream dummyVert;
750 	std::stringstream dummyFrag;
751 
752 	dummyVert
753 		<< "#version 450\n"
754 		<< "layout(location = 0) out vec4 rgba;\n"
755 		<< "void main() {\n"
756 		<< "    vec2 pos2 = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
757 		<< "	vec3 pos3 = vec3(pos2, 0.0f) * gl_InstanceIndex;\n"
758 		<< "    gl_Position = vec4(pos3, 1.0f);\n"
759 		<< "    rgba = vec4(0.0f, pos3.zyx);\n"
760 		<< "}\n";
761 
762 	dummyFrag
763 		<< "#version 450\n"
764 		<< "layout(location = 0) in vec4 rgba;\n"
765 		<< "layout(location = 0) out vec4 color;\n"
766 		<< "void main() {\n"
767 		<< "	color = rgba * rgba;\n"
768 		<< "}\n";
769 
770 	programCollection.glslSources.add("dummyVert") << glu::VertexSource(dummyVert.str());
771 	programCollection.glslSources.add("dummyFrag") << glu::FragmentSource(dummyFrag.str());
772 }
773 
774 
775 class ShaderObjectDispatchPerformanceInstance : public vkt::TestInstance
776 {
777 public:
ShaderObjectDispatchPerformanceInstance(Context& context, const DispatchType dispatchType)778 							ShaderObjectDispatchPerformanceInstance		(Context& context, const DispatchType dispatchType)
779 																		: vkt::TestInstance	(context)
780 																		, m_dispatchType	(dispatchType)
781 																		{}
~ShaderObjectDispatchPerformanceInstance(void)782 	virtual					~ShaderObjectDispatchPerformanceInstance	(void) {}
783 
784 	tcu::TestStatus			iterate										(void) override;
785 
786 private:
787 	const DispatchType	m_dispatchType;
788 };
789 
iterate(void)790 tcu::TestStatus ShaderObjectDispatchPerformanceInstance::iterate (void)
791 {
792 	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
793 	const vk::VkDevice					device						= m_context.getDevice();
794 	const vk::VkQueue					queue						= m_context.getUniversalQueue();
795 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
796 	auto&								alloc						= m_context.getDefaultAllocator();
797 
798 	const vk::VkDeviceSize				bufferSizeBytes				= sizeof(deUint32) * 16;
799 	const vk::BufferWithMemory			outputBuffer				(vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
800 	const bool							tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
801 	const bool							geometrySupported			= m_context.getDeviceFeatures().geometryShader;
802 
803 	const auto& binaries			= m_context.getBinaryCollection();
804 
805 	const auto& comp				= binaries.get("comp");
806 	const auto  compShaderModule	= createShaderModule(vk, device, comp);
807 
808 	const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
809 		vk::DescriptorSetLayoutBuilder()
810 		.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
811 		.build(vk, device));
812 
813 	const vk::Unique<vk::VkDescriptorPool> descriptorPool(
814 		vk::DescriptorPoolBuilder()
815 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
816 		.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
817 	const auto	pipelineLayout	= makePipelineLayout(vk, device, descriptorSetLayout.get());
818 
819 	const vk::Unique<vk::VkDescriptorSet>	descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
820 	const vk::VkDescriptorBufferInfo		descriptorInfo = vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
821 	vk::DescriptorSetUpdateBuilder()
822 		.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
823 		.update(vk, device);
824 
825 	const auto							compShader		= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_COMPUTE_BIT, binaries.get("comp"), tessellationSupported, geometrySupported, &*descriptorSetLayout));
826 	const vk::VkPipelineCreateFlags		pipelineFlags	= (m_dispatchType == DISPATCH) ? (vk::VkPipelineCreateFlags)0u : (vk::VkPipelineCreateFlags)vk::VK_PIPELINE_CREATE_DISPATCH_BASE_BIT;
827 	const auto							computePipeline	= vk::makeComputePipeline(vk, device, pipelineLayout.get(), pipelineFlags, nullptr, compShaderModule.get(), (vk::VkPipelineShaderStageCreateFlags)0u);
828 
829 	const vk::Move<vk::VkCommandPool>	cmdPool			(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
830 	const vk::Move<vk::VkCommandBuffer>	cmdBuffer		(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
831 
832 	vk::BufferWithMemory				indirectBuffer	(vk, device, alloc, vk::makeBufferCreateInfo(sizeof(vk::VkDispatchIndirectCommand), vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
833 
834 	vk::VkDispatchIndirectCommand*		indirectDataPtr = reinterpret_cast<vk::VkDispatchIndirectCommand*>(indirectBuffer.getAllocation().getHostPtr());
835 	indirectDataPtr->x = 1;
836 	indirectDataPtr->y = 1;
837 	indirectDataPtr->z = 1;
838 
839 	std::chrono::nanoseconds			time	= std::chrono::nanoseconds(0);
840 	std::chrono::nanoseconds			refTime = std::chrono::nanoseconds(0);
841 
842 	for (deUint32 i = 0; i < 100; ++i)
843 	{
844 		vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
845 		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1, &descriptorSet.get(), 0, DE_NULL);
846 		vk::bindComputeShader(vk, *cmdBuffer, *compShader);
847 		if (m_dispatchType == DISPATCH)
848 		{
849 			const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
850 			vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
851 			time += std::chrono::high_resolution_clock::now() - shaderObjectStart;
852 		}
853 		else if (m_dispatchType == DISPATCH_BASE)
854 		{
855 			const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
856 			vk.cmdDispatchBase(*cmdBuffer, 1, 1, 1, 0, 0, 0);
857 			time += std::chrono::high_resolution_clock::now() - shaderObjectStart;
858 		}
859 		else if (m_dispatchType == DISPATCH_INDIRECT)
860 		{
861 			const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
862 			vk.cmdDispatchIndirect(*cmdBuffer, *indirectBuffer, 0u);
863 			time += std::chrono::high_resolution_clock::now() - shaderObjectStart;
864 		}
865 		vk::endCommandBuffer(vk, *cmdBuffer);
866 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
867 
868 		vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
869 		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1, &descriptorSet.get(), 0, DE_NULL);
870 		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
871 		if (m_dispatchType == DISPATCH)
872 		{
873 			const auto pipelineStart = std::chrono::high_resolution_clock::now();
874 			vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
875 			refTime += std::chrono::high_resolution_clock::now() - pipelineStart;
876 		}
877 		else if (m_dispatchType == DISPATCH_BASE)
878 		{
879 			const auto pipelineStart = std::chrono::high_resolution_clock::now();
880 			vk.cmdDispatchBase(*cmdBuffer, 1, 1, 1, 0, 0, 0);
881 			refTime += std::chrono::high_resolution_clock::now() - pipelineStart;
882 		}
883 		else if (m_dispatchType == DISPATCH_INDIRECT)
884 		{
885 			const auto pipelineStart = std::chrono::high_resolution_clock::now();
886 			vk.cmdDispatchIndirect(*cmdBuffer, *indirectBuffer, 0u);
887 			refTime += std::chrono::high_resolution_clock::now() - pipelineStart;
888 		}
889 		vk::endCommandBuffer(vk, *cmdBuffer);
890 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
891 
892 		// Ignore first iteration, there is a penalty on the first call
893 		if (i == 0)
894 		{
895 			time = std::chrono::nanoseconds(0);
896 			refTime = std::chrono::nanoseconds(0);
897 		}
898 	}
899 
900 	if (time > refTime * 1.05f)
901 		return tcu::TestStatus::fail("Shader object dispatch was more than 5% slower than compute pipeline dispatch");
902 	return tcu::TestStatus::pass("Pass");
903 }
904 
905 class ShaderObjectDispatchPerformanceCase : public vkt::TestCase
906 {
907 public:
ShaderObjectDispatchPerformanceCase(tcu::TestContext& testCtx, const std::string& name, const DispatchType dispatchType)908 					ShaderObjectDispatchPerformanceCase		(tcu::TestContext& testCtx, const std::string& name, const DispatchType dispatchType)
909 															: vkt::TestCase		(testCtx, name)
910 															, m_dispatchType	(dispatchType)
911 															{}
~ShaderObjectDispatchPerformanceCase(void)912 	virtual			~ShaderObjectDispatchPerformanceCase	(void) {}
913 
914 	void			checkSupport							(vkt::Context& context) const override;
915 	virtual void	initPrograms							(vk::SourceCollections& programCollection) const override;
916 	TestInstance*	createInstance							(Context& context) const override { return new ShaderObjectDispatchPerformanceInstance(context, m_dispatchType); }
917 
918 private:
919 	const DispatchType	m_dispatchType;
920 };
921 
checkSupport(Context& context) const922 void ShaderObjectDispatchPerformanceCase::checkSupport (Context& context) const
923 {
924 	context.requireDeviceFunctionality("VK_EXT_shader_object");
925 }
926 
initPrograms(vk::SourceCollections& programCollection) const927 void ShaderObjectDispatchPerformanceCase::initPrograms (vk::SourceCollections& programCollection) const
928 {
929 	vk::addBasicShaderObjectShaders(programCollection);
930 }
931 
932 
933 class ShaderObjectBinaryPerformanceInstance : public vkt::TestInstance
934 {
935 public:
ShaderObjectBinaryPerformanceInstance(Context& context, BinaryType type)936 							ShaderObjectBinaryPerformanceInstance	(Context& context, BinaryType type)
937 																	: vkt::TestInstance	(context)
938 																	, m_type			(type)
939 																	{}
~ShaderObjectBinaryPerformanceInstance(void)940 	virtual					~ShaderObjectBinaryPerformanceInstance	(void) {}
941 
942 	tcu::TestStatus			iterate									(void) override;
943 private:
944 	const BinaryType	m_type;
945 };
946 
iterate(void)947 tcu::TestStatus ShaderObjectBinaryPerformanceInstance::iterate (void)
948 {
949 	const vk::DeviceInterface&	vk						= m_context.getDeviceInterface();
950 	const vk::VkDevice			device					= m_context.getDevice();
951 	auto&						alloc					= m_context.getDefaultAllocator();
952 	const bool					tessellationSupported	= m_context.getDeviceFeatures().tessellationShader;
953 	const bool					geometrySupported		= m_context.getDeviceFeatures().geometryShader;
954 
955 	const auto&					binaries				= m_context.getBinaryCollection();
956 
957 	std::chrono::nanoseconds	time					= std::chrono::nanoseconds(0);
958 	std::chrono::nanoseconds	refTime					= std::chrono::nanoseconds(0);
959 
960 	for (deUint32 i = 0; i < 100; ++i)
961 	{
962 		const auto					spirvCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, binaries.get("vert"), tessellationSupported, geometrySupported);
963 		vk::VkShaderEXT				spirvShader;
964 		const auto spirvStart = std::chrono::high_resolution_clock::now();
965 		vk.createShadersEXT(device, 1u, &spirvCreateInfo, DE_NULL, &spirvShader);
966 		const auto spirvEnd = std::chrono::high_resolution_clock::now();
967 		if (m_type == BINARY_SHADER_CREATE)
968 			refTime += spirvEnd - spirvStart;
969 
970 		size_t						dataSize = 0;
971 		vk.getShaderBinaryDataEXT(device, spirvShader, &dataSize, DE_NULL);
972 		std::vector<deUint8>		data(dataSize);
973 		vk.getShaderBinaryDataEXT(device, spirvShader, &dataSize, data.data());
974 
975 		const vk::VkShaderCreateInfoEXT binaryShaderCreateInfo =
976 		{
977 			vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
978 			DE_NULL,										// const void*					pNext;
979 			0u,												// VkShaderCreateFlagsEXT		flags;
980 			vk::VK_SHADER_STAGE_VERTEX_BIT,					// VkShaderStageFlagBits		stage;
981 			0u,												// VkShaderStageFlags			nextStage;
982 			vk::VK_SHADER_CODE_TYPE_BINARY_EXT,				// VkShaderCodeTypeEXT			codeType;
983 			dataSize,										// size_t						codeSize;
984 			data.data(),									// const void*					pCode;
985 			"main",											// const char*					pName;
986 			0u,												// uint32_t						setLayoutCount;
987 			DE_NULL,										// VkDescriptorSetLayout*		pSetLayouts;
988 			0u,												// uint32_t						pushConstantRangeCount;
989 			DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
990 			DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
991 		};
992 
993 		vk::VkShaderEXT binaryShader;
994 		const auto binaryStart = std::chrono::high_resolution_clock::now();
995 		vk.createShadersEXT(device, 1, &binaryShaderCreateInfo, DE_NULL, &binaryShader);
996 		time += std::chrono::high_resolution_clock::now() - binaryStart;
997 
998 		const auto					bufferCreateInfo	= vk::makeBufferCreateInfo(dataSize, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
999 		vk::Move<vk::VkBuffer>		buffer				= vk::createBuffer(vk, device, &bufferCreateInfo);
1000 		const auto					bufferMemReqs		= vk::getBufferMemoryRequirements(vk, device, *buffer);
1001 		const auto					memoryProperties	= vk::getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
1002 		const auto					hostCachedDeviceLocal	= bufferMemReqs.memoryTypeBits & vk::getCompatibleMemoryTypes(memoryProperties, vk::MemoryRequirement::Cached | vk::MemoryRequirement::Local | vk::MemoryRequirement::HostVisible);
1003 
1004 		vk::MemoryRequirement		memoryRequirements	= (hostCachedDeviceLocal != 0) ?
1005 														  vk::MemoryRequirement::Cached | vk::MemoryRequirement::Local | vk::MemoryRequirement::HostVisible :
1006 														  vk::MemoryRequirement::Coherent | vk::MemoryRequirement::Local | vk::MemoryRequirement::HostVisible;
1007 		vk::BufferWithMemory		bufferWithMemory	(vk, device, alloc, bufferCreateInfo, memoryRequirements);
1008 		const vk::Allocation&		bufferAlloc			= bufferWithMemory.getAllocation();
1009 		const auto memcpyStart = std::chrono::high_resolution_clock::now();
1010 		memcpy(bufferAlloc.getHostPtr(), data.data(), dataSize);
1011 		flushAlloc(vk, device, bufferAlloc);
1012 		const auto memcpyEnd = std::chrono::high_resolution_clock::now();
1013 		if (m_type == BINARY_MEMCPY)
1014 			refTime += memcpyEnd - memcpyStart;
1015 
1016 		vk.destroyShaderEXT(device, spirvShader, DE_NULL);
1017 		vk.destroyShaderEXT(device, binaryShader, DE_NULL);
1018 	}
1019 
1020 	if (m_type == BINARY_SHADER_CREATE)
1021 	{
1022 		if (time > refTime * 1.05f)
1023 			return tcu::TestStatus::fail("Binary shader object create time is more than 5% slower than spirv shader object create time");
1024 	}
1025 	else if (m_type == BINARY_MEMCPY)
1026 	{
1027 		if (time > refTime * 1.5f)
1028 			return tcu::TestStatus::fail("Binary shader object create time is more than 50% slower than memcpy of an equal amount of data");
1029 	}
1030 
1031 	return tcu::TestStatus::pass("Pass");
1032 }
1033 
1034 class ShaderObjectBinaryPerformanceCase : public vkt::TestCase
1035 {
1036 public:
ShaderObjectBinaryPerformanceCase(tcu::TestContext& testCtx, const std::string& name, BinaryType type)1037 					ShaderObjectBinaryPerformanceCase	(tcu::TestContext& testCtx, const std::string& name, BinaryType type)
1038 														: vkt::TestCase		(testCtx, name)
1039 														, m_type			(type)
1040 														{}
~ShaderObjectBinaryPerformanceCase(void)1041 	virtual			~ShaderObjectBinaryPerformanceCase	(void) {}
1042 
1043 	void			checkSupport						(vkt::Context& context) const override;
1044 	virtual void	initPrograms						(vk::SourceCollections& programCollection) const override;
1045 	TestInstance*	createInstance						(Context& context) const override { return new ShaderObjectBinaryPerformanceInstance(context, m_type); }
1046 private:
1047 	const BinaryType	m_type;
1048 };
1049 
checkSupport(Context& context) const1050 void ShaderObjectBinaryPerformanceCase::checkSupport (Context& context) const
1051 {
1052 	context.requireDeviceFunctionality("VK_EXT_shader_object");
1053 }
1054 
initPrograms(vk::SourceCollections& programCollection) const1055 void ShaderObjectBinaryPerformanceCase::initPrograms (vk::SourceCollections& programCollection) const
1056 {
1057 	vk::addBasicShaderObjectShaders(programCollection);
1058 }
1059 
1060 }
1061 
1062 
createShaderObjectPerformanceTests(tcu::TestContext& testCtx)1063 tcu::TestCaseGroup* createShaderObjectPerformanceTests (tcu::TestContext& testCtx)
1064 {
1065 	de::MovePtr<tcu::TestCaseGroup> performanceGroup(new tcu::TestCaseGroup(testCtx, "performance"));
1066 
1067 	const struct
1068 	{
1069 		DrawType	drawType;
1070 		const char* name;
1071 	} drawTypeTests[] =
1072 	{
1073 		{ DRAW,							"draw"							},
1074 		{ DRAW_INDEXED,					"draw_indexed"					},
1075 		{ DRAW_INDEXED_INDIRECT,		"draw_indexed_indirect"			},
1076 		{ DRAW_INDEXED_INDIRECT_COUNT,	"draw_indexed_indirect_count"	},
1077 		{ DRAW_INDIRECT,				"draw_indirect"					},
1078 		{ DRAW_INDIRECT_COUNT,			"draw_indirect_count"			},
1079 	};
1080 
1081 	const struct
1082 	{
1083 		TestType	testTpye;
1084 		const char* name;
1085 	} typeTests[] =
1086 	{
1087 		{ DRAW_STATIC_PIPELINE,		"static_pipeline"	},
1088 		{ DRAW_DYNAMIC_PIPELINE,	"dynamic_pipeline"	},
1089 		{ DRAW_LINKED_SHADERS,		"linked_shaders"	},
1090 		{ DRAW_BINARY,				"binary_shaders"	},
1091 	};
1092 
1093 	for (const auto& drawType : drawTypeTests)
1094 	{
1095 		for (const auto& typeTest : typeTests)
1096 		{
1097 			performanceGroup->addChild(new ShaderObjectPerformanceCase(testCtx, std::string(drawType.name) + "_" + std::string(typeTest.name), drawType.drawType, typeTest.testTpye));
1098 		}
1099 	}
1100 	performanceGroup->addChild(new ShaderObjectPerformanceCase(testCtx, "binary_bind_shaders", DRAW, DRAW_BINARY_BIND));
1101 
1102 	performanceGroup->addChild(new ShaderObjectDispatchPerformanceCase(testCtx, "dispatch", DISPATCH));
1103 	performanceGroup->addChild(new ShaderObjectDispatchPerformanceCase(testCtx, "dispatch_base", DISPATCH_BASE));
1104 	performanceGroup->addChild(new ShaderObjectDispatchPerformanceCase(testCtx, "dispatch_indirect", DISPATCH_INDIRECT));
1105 
1106 	performanceGroup->addChild(new ShaderObjectBinaryPerformanceCase(testCtx, "binary_shader_create", BINARY_SHADER_CREATE));
1107 	performanceGroup->addChild(new ShaderObjectBinaryPerformanceCase(testCtx, "binary_memcpy", BINARY_MEMCPY));
1108 
1109 	return performanceGroup.release();
1110 }
1111 
1112 } // ShaderObject
1113 } // vkt
1114