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 Pipeline Interaction Tests
23 *//*--------------------------------------------------------------------*/
24
25#include "vktShaderObjectCreateTests.hpp"
26#include "deUniquePtr.hpp"
27#include "tcuTestCase.hpp"
28#include "vktTestCase.hpp"
29#include "vkCmdUtil.hpp"
30#include "vkImageUtil.hpp"
31#include "vkBarrierUtil.hpp"
32#include "vktShaderObjectCreateUtil.hpp"
33#include "vkObjUtil.hpp"
34#include "deRandom.hpp"
35#include "vkBuilderUtil.hpp"
36
37namespace vkt
38{
39namespace ShaderObject
40{
41
42namespace
43{
44
45enum TestType {
46	SHADER_OBJECT = 0,
47	MAX_PIPELINE,
48	MAX_PIPELINE_SHADER_OBJECT_MAX_PIPELINE,
49	SHADER_OBJECT_MAX_PIPELINE_SHADER_OBJECT,
50	MIN_PIPELINE_SHADER_OBJECT,
51	RENDER_PASS_PIPELINE_SHADER_OBJECT,
52	RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN,
53	SHADER_OBJECT_MIN_PIPELINE,
54	COMPUTE_SHADER_OBJECT_MIN_PIPELINE,
55	SHADER_OBJECT_COMPUTE_PIPELINE,
56};
57
58struct TestParams {
59	TestType	testType;
60};
61
62struct StageTestParams {
63	bool vertShader;
64	bool tessShader;
65	bool geomShader;
66	bool fragShader;
67};
68
69class ShaderObjectPipelineInteractionInstance : public vkt::TestInstance
70{
71public:
72							ShaderObjectPipelineInteractionInstance		(Context& context, const TestParams& params)
73																		: vkt::TestInstance	(context)
74																		, m_params			(params)
75																		{}
76	virtual					~ShaderObjectPipelineInteractionInstance	(void) {}
77
78	tcu::TestStatus			iterate										(void) override;
79private:
80	bool					verifyImage									(de::MovePtr<vk::BufferWithMemory>& outputBuffer, deUint32 drawCount);
81	deUint32				getDrawCount								(void);
82	TestParams				m_params;
83
84	const vk::VkFormat		colorAttachmentFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
85	const vk::VkRect2D		renderArea					= { {0u, 0u, }, {32u, 32u, } };
86};
87
88deUint32 ShaderObjectPipelineInteractionInstance::getDrawCount (void)
89{
90	switch (m_params.testType) {
91		case SHADER_OBJECT:
92			return 1;
93		case MAX_PIPELINE:
94			return 1;
95		case MAX_PIPELINE_SHADER_OBJECT_MAX_PIPELINE:
96			return 3;
97		case SHADER_OBJECT_MAX_PIPELINE_SHADER_OBJECT:
98			return 3;
99		case MIN_PIPELINE_SHADER_OBJECT:
100			return 2;
101		case RENDER_PASS_PIPELINE_SHADER_OBJECT:
102			return 1;
103		case RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN:
104			return 1;
105		case SHADER_OBJECT_MIN_PIPELINE:
106			return 2;
107		case COMPUTE_SHADER_OBJECT_MIN_PIPELINE:
108			return 1;
109		case SHADER_OBJECT_COMPUTE_PIPELINE:
110			return 1;
111	}
112	return 0;
113}
114
115bool extensionEnabled (const std::vector<std::string>& deviceExtensions, const std::string& ext)
116{
117	return std::find(deviceExtensions.begin(), deviceExtensions.end(), ext) != deviceExtensions.end();
118}
119
120tcu::TestStatus ShaderObjectPipelineInteractionInstance::iterate (void)
121{
122	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
123	const vk::VkDevice					device						= m_context.getDevice();
124	const vk::VkQueue					queue						= m_context.getUniversalQueue();
125	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
126	auto&								alloc						= m_context.getDefaultAllocator();
127	const auto							deviceExtensions			= vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
128	const bool							tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
129	const bool							geometrySupported			= m_context.getDeviceFeatures().geometryShader;
130	const bool							taskSupported				= m_context.getMeshShaderFeatures().taskShader;
131	const bool							meshSupported				= m_context.getMeshShaderFeatures().meshShader;
132
133	const auto							subresourceRange			= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
134
135	const vk::VkImageCreateInfo			createInfo					=
136	{
137		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType
138		DE_NULL,																		// const void*				pNext
139		0u,																				// VkImageCreateFlags		flags
140		vk::VK_IMAGE_TYPE_2D,															// VkImageType				imageType
141		colorAttachmentFormat,															// VkFormat					format
142		{ renderArea.extent.width, renderArea.extent.height, 1 },						// VkExtent3D				extent
143		1u,																				// uint32_t					mipLevels
144		1u,																				// uint32_t					arrayLayers
145		vk::VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples
146		vk::VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling
147		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
148		vk::VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode
149		0,																				// uint32_t					queueFamilyIndexCount
150		DE_NULL,																		// const uint32_t*			pQueueFamilyIndices
151		vk::VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout
152	};
153
154	de::MovePtr<vk::ImageWithMemory>	image						= de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
155	const auto							imageView					= vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
156
157	const vk::VkDeviceSize				colorOutputBufferSize		= renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
158	de::MovePtr<vk::BufferWithMemory>	colorOutputBuffer			= de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
159		vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
160
161	const vk::VkCommandPoolCreateInfo	cmdPoolInfo =
162	{
163		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// sType
164		DE_NULL,												// pNext
165		vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// flags
166		queueFamilyIndex,										// queuefamilyindex
167	};
168
169	const vk::Move<vk::VkCommandPool>	cmdPool					(createCommandPool(vk, device, &cmdPoolInfo));
170	const vk::Move<vk::VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
171	const vk::Move<vk::VkCommandBuffer>	copyCmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
172
173	const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
174		vk::DescriptorSetLayoutBuilder()
175		.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
176		.build(vk, device));
177
178	const vk::Unique<vk::VkDescriptorPool> descriptorPool(
179		vk::DescriptorPoolBuilder()
180		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
181		.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
182
183	const auto					pipelineLayout			= makePipelineLayout(vk, device);
184	const auto					computePipelineLayout	= makePipelineLayout(vk, device, descriptorSetLayout.get());
185
186	const auto&					binaries			= m_context.getBinaryCollection();
187	const auto&					vert1				= binaries.get("vert1");
188	const auto&					vert2				= binaries.get("vert2");
189	const auto&					vert3				= binaries.get("vert3");
190	const auto&					tesc				= binaries.get("tesc");
191	const auto&					tese				= binaries.get("tese");
192	const auto&					geom				= binaries.get("geom");
193	const auto&					frag1				= binaries.get("frag1");
194	const auto&					frag2				= binaries.get("frag2");
195	const auto&					frag3				= binaries.get("frag3");
196	const auto&					comp				= binaries.get("comp");
197
198	// Todo
199	vk::VkDescriptorSetLayout	layout				= descriptorSetLayout.get();
200
201	vk::VkShaderCreateInfoEXT	vertCreateInfo1		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert1, tessellationSupported, geometrySupported);
202	vk::VkShaderCreateInfoEXT	vertCreateInfo2		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert2, tessellationSupported, geometrySupported);
203	vk::VkShaderCreateInfoEXT	vertCreateInfo3		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert3, tessellationSupported, geometrySupported);
204	vk::VkShaderCreateInfoEXT	tescCreateInfo		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, tesc, tessellationSupported, geometrySupported);
205	vk::VkShaderCreateInfoEXT	teseCreateInfo		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, tese, tessellationSupported, geometrySupported);
206	vk::VkShaderCreateInfoEXT	geomCreateInfo		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, geom, tessellationSupported, geometrySupported);
207	vk::VkShaderCreateInfoEXT	fragCreateInfo1		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag1, tessellationSupported, geometrySupported);
208	vk::VkShaderCreateInfoEXT	fragCreateInfo2		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag2, tessellationSupported, geometrySupported);
209	vk::VkShaderCreateInfoEXT	fragCreateInfo3		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag3, tessellationSupported, geometrySupported);
210	vk::VkShaderCreateInfoEXT	compCreateInfo		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_COMPUTE_BIT, comp, tessellationSupported, geometrySupported, &layout);
211
212	vk::Move<vk::VkShaderEXT>	vertShader1			= vk::createShader(vk, device, vertCreateInfo1);
213	vk::Move<vk::VkShaderEXT>	vertShader2			= vk::createShader(vk, device, vertCreateInfo2);
214	vk::Move<vk::VkShaderEXT>	vertShader3			= vk::createShader(vk, device, vertCreateInfo3);
215	vk::Move<vk::VkShaderEXT>	tescShader			= vk::createShader(vk, device, tescCreateInfo);
216	vk::Move<vk::VkShaderEXT>	teseShader			= vk::createShader(vk, device, teseCreateInfo);
217	vk::Move<vk::VkShaderEXT>	geomShader			= vk::createShader(vk, device, geomCreateInfo);
218	vk::Move<vk::VkShaderEXT>	fragShader1			= vk::createShader(vk, device, fragCreateInfo1);
219	vk::Move<vk::VkShaderEXT>	fragShader2			= vk::createShader(vk, device, fragCreateInfo2);
220	vk::Move<vk::VkShaderEXT>	fragShader3			= vk::createShader(vk, device, fragCreateInfo3);
221	vk::Move<vk::VkShaderEXT>	compShader			= vk::createShader(vk, device, compCreateInfo);
222
223	const auto					vertShaderModule1	= createShaderModule(vk, device, vert1);
224	const auto					vertShaderModule2	= createShaderModule(vk, device, vert2);
225	const auto					vertShaderModule3	= createShaderModule(vk, device, vert3);
226	const auto					tescShaderModule	= createShaderModule(vk, device, tesc);
227	const auto					teseShaderModule	= createShaderModule(vk, device, tese);
228	const auto					geomShaderModule	= createShaderModule(vk, device, geom);
229	const auto					fragShaderModule1	= createShaderModule(vk, device, frag1);
230	const auto					fragShaderModule2	= createShaderModule(vk, device, frag2);
231	const auto					fragShaderModule3	= createShaderModule(vk, device, frag3);
232	const auto					compShaderModule	= createShaderModule(vk, device, comp);
233
234	const auto					renderPass			= vk::makeRenderPass(vk, device, colorAttachmentFormat, vk::VK_FORMAT_UNDEFINED, vk::VK_ATTACHMENT_LOAD_OP_CLEAR, vk::VK_IMAGE_LAYOUT_GENERAL);
235	const auto					framebuffer			= vk::makeFramebuffer(vk, device, *renderPass, 1u, &*imageView, renderArea.extent.width, renderArea.extent.height);
236
237	const vk::VkPipelineVertexInputStateCreateInfo		vertexInputStateParams			=
238	{
239		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
240		DE_NULL,														// const void*								pNext;
241		0u,																// VkPipelineVertexInputStateCreateFlags	flags;
242		0u,																// deUint32									vertexBindingDescriptionCount;
243		DE_NULL,														// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
244		0u,																// deUint32									vertexAttributeDescriptionCount;
245		DE_NULL															// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
246	};
247
248	const vk::VkPipelineTessellationStateCreateInfo		tessStateCreateInfo				=
249	{
250		vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
251		DE_NULL,														//	const void*								pNext;
252		0u,																//	VkPipelineTessellationStateCreateFlags	flags;
253		4u,																//	uint32_t								patchControlPoints;
254	};
255
256	const vk::VkPipelineInputAssemblyStateCreateInfo	pipelineInputAssemblyStateInfo	=
257	{
258		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
259		DE_NULL,															// const void*                                 pNext;
260		(vk::VkPipelineInputAssemblyStateCreateFlags)0u,					// VkPipelineInputAssemblyStateCreateFlags     flags;
261		vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,								// VkPrimitiveTopology                         topology;
262		VK_FALSE,															// VkBool32                                    primitiveRestartEnable;
263	};
264
265	vk::VkPipelineRenderingCreateInfo					pipelineRenderingCreateInfo		=
266	{
267		vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,	// VkStructureType	sType
268		DE_NULL,												// const void*		pNext
269		0u,														// uint32_t			viewMask
270		1u,														// uint32_t			colorAttachmentCount
271		&colorAttachmentFormat,									// const VkFormat*	pColorAttachmentFormats
272		vk::VK_FORMAT_UNDEFINED,								// VkFormat			depthAttachmentFormat
273		vk::VK_FORMAT_UNDEFINED,								// VkFormat			stencilAttachmentFormat
274	};
275
276	const vk::VkViewport								viewport						= vk::makeViewport(renderArea.extent);
277	const vk::VkRect2D									scissor							= vk::makeRect2D(renderArea.extent);
278
279	bool createDynamicPipeline = m_params.testType != MIN_PIPELINE_SHADER_OBJECT && m_params.testType != SHADER_OBJECT_MIN_PIPELINE && m_params.testType != COMPUTE_SHADER_OBJECT_MIN_PIPELINE && m_params.testType != RENDER_PASS_PIPELINE_SHADER_OBJECT && m_params.testType != RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN;
280
281	const vk::VkPipelineViewportStateCreateInfo			viewportStateCreateInfo			=
282	{
283		vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType
284		DE_NULL,													// const void*                                 pNext
285		(vk::VkPipelineViewportStateCreateFlags)0u,					// VkPipelineViewportStateCreateFlags          flags
286		createDynamicPipeline ? 0u : 1u,							// deUint32                                    viewportCount
287		&viewport,													// const VkViewport*                           pViewports
288		createDynamicPipeline ? 0u : 1u,							// deUint32                                    scissorCount
289		&scissor,													// const VkRect2D*                             pScissors
290	};
291
292	const auto& edsFeatures		= m_context.getExtendedDynamicStateFeaturesEXT();
293	const auto& eds2Features	= m_context.getExtendedDynamicState2FeaturesEXT();
294	const auto& eds3Features	= m_context.getExtendedDynamicState3FeaturesEXT();
295	const auto& viFeatures		= m_context.getVertexInputDynamicStateFeaturesEXT();
296
297	std::vector<vk::VkDynamicState> dynamicStates = {
298		vk::VK_DYNAMIC_STATE_LINE_WIDTH,
299		vk::VK_DYNAMIC_STATE_DEPTH_BIAS,
300		vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS,
301		vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS,
302		vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
303		vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
304		vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE,
305	};
306
307	if (edsFeatures.extendedDynamicState)
308	{
309		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CULL_MODE_EXT);
310		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT);
311		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
312		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
313		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
314		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
315		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
316		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
317		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT);
318		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT);
319		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
320		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT);
321	}
322	else
323	{
324		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT);
325		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR);
326	}
327	if (eds2Features.extendedDynamicState2)
328	{
329		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE);
330		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
331		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE);
332	}
333	if (eds2Features.extendedDynamicState2LogicOp)
334		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT);
335	if (eds2Features.extendedDynamicState2PatchControlPoints)
336		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
337
338	if (eds3Features.extendedDynamicState3TessellationDomainOrigin)
339		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT);
340	if (eds3Features.extendedDynamicState3DepthClampEnable)
341		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT);
342	if (eds3Features.extendedDynamicState3PolygonMode)
343		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT);
344	if (eds3Features.extendedDynamicState3RasterizationSamples)
345		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
346	if (eds3Features.extendedDynamicState3SampleMask)
347		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
348	if (eds3Features.extendedDynamicState3AlphaToCoverageEnable)
349		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
350	if (eds3Features.extendedDynamicState3AlphaToOneEnable)
351		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
352	if (eds3Features.extendedDynamicState3LogicOpEnable)
353		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
354	if (eds3Features.extendedDynamicState3ColorBlendEnable)
355		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
356	if (eds3Features.extendedDynamicState3ColorBlendEquation)
357		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
358	if (eds3Features.extendedDynamicState3ColorWriteMask)
359		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
360	if (viFeatures.vertexInputDynamicState)
361		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
362
363	if (extensionEnabled(deviceExtensions, "VK_EXT_transform_feedback") && eds3Features.extendedDynamicState3RasterizationStream)
364		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
365	if (extensionEnabled(deviceExtensions, "VK_EXT_blend_operation_advanced") && eds3Features.extendedDynamicState3ColorBlendAdvanced)
366		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
367	if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization") && eds3Features.extendedDynamicState3ConservativeRasterizationMode)
368		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
369	if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") && eds3Features.extendedDynamicState3CoverageModulationMode)
370		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV);
371	if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") && eds3Features.extendedDynamicState3CoverageModulationTableEnable)
372		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV);
373	if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") && eds3Features.extendedDynamicState3CoverageModulationTable)
374		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV);
375	if (extensionEnabled(deviceExtensions, "VK_NV_coverage_reduction_mode") && eds3Features.extendedDynamicState3CoverageReductionMode)
376		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
377	if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color") && eds3Features.extendedDynamicState3CoverageToColorEnable)
378		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV);
379	if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color") && eds3Features.extendedDynamicState3CoverageToColorLocation)
380		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV);
381	if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_enable") && eds3Features.extendedDynamicState3DepthClipEnable)
382		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT);
383	if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_control") && eds3Features.extendedDynamicState3DepthClipNegativeOneToOne)
384		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT);
385	if (extensionEnabled(deviceExtensions, "VK_EXT_color_write_enable"))
386		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
387	if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization") && eds3Features.extendedDynamicState3ExtraPrimitiveOverestimationSize)
388		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
389	if (extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization") && eds3Features.extendedDynamicState3LineRasterizationMode)
390		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
391	if (extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization") && eds3Features.extendedDynamicState3LineStippleEnable)
392		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
393	if (extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization"))
394		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
395	if (extensionEnabled(deviceExtensions, "VK_EXT_provoking_vertex") && eds3Features.extendedDynamicState3ProvokingVertexMode)
396		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
397	if (extensionEnabled(deviceExtensions, "VK_KHR_fragment_shading_rate"))
398		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR);
399	if (extensionEnabled(deviceExtensions, "VK_NV_representative_fragment_test") && eds3Features.extendedDynamicState3RepresentativeFragmentTestEnable)
400		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV);
401	if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations") && eds3Features.extendedDynamicState3SampleLocationsEnable)
402		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
403	if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations"))
404		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
405	if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image") && eds3Features.extendedDynamicState3ShadingRateImageEnable)
406		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
407	if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
408		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV);
409	if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
410		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV);
411	if (extensionEnabled(deviceExtensions, "VK_NV_viewport_swizzle") && eds3Features.extendedDynamicState3ViewportSwizzle)
412		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV);
413	if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling") && eds3Features.extendedDynamicState3ViewportWScalingEnable)
414		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV);
415	if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling"))
416		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV);
417	if (extensionEnabled(deviceExtensions, "VK_NV_scissor_exclusive"))
418		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV);
419	if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
420		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
421	if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
422		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
423	if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
424		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT);
425
426	const vk::VkPipelineDynamicStateCreateInfo			dynamicStateCreateInfo			=
427	{
428		vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
429		DE_NULL,													//	const void*							pNext;
430		(vk::VkPipelineDynamicStateCreateFlags)0u,					//	VkPipelineDynamicStateCreateFlags	flags;
431		static_cast<deUint32>(dynamicStates.size()),				//	deUint32							dynamicStateCount;
432		dynamicStates.data(),										//	const VkDynamicState*				pDynamicStates;
433	};
434	const vk::VkPipelineDynamicStateCreateInfo* pipelineDynamicState = (createDynamicPipeline) ? &dynamicStateCreateInfo : DE_NULL;
435
436	const vk::VkDeviceSize					bufferSizeBytes = sizeof(deUint32) * 4;
437
438	const vk::Unique<vk::VkDescriptorSet>	descriptorSet	(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
439	const vk::BufferWithMemory outputBuffer(vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
440
441	const vk::VkDescriptorBufferInfo		descriptorInfo	= vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
442	vk::DescriptorSetUpdateBuilder()
443		.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
444		.update(vk, device);
445
446	vk::VkPipelineRenderingCreateInfo*		pPipelineRenderingCreateInfo	= &pipelineRenderingCreateInfo;
447	vk::VkRenderPass						renderPassHandle				= VK_NULL_HANDLE;
448	if (m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT || m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN)
449	{
450		pPipelineRenderingCreateInfo = DE_NULL;
451		renderPassHandle = *renderPass;
452	}
453
454	const auto					pipeline1				= makeGraphicsPipeline(vk, device, pipelineLayout.get(), vertShaderModule1.get(), tescShaderModule.get(), teseShaderModule.get(), geomShaderModule.get(), fragShaderModule1.get(), renderPassHandle, 0u, &vertexInputStateParams, &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL, DE_NULL, pipelineDynamicState, pPipelineRenderingCreateInfo);
455	const auto					pipeline2				= makeGraphicsPipeline(vk, device, pipelineLayout.get(), vertShaderModule2.get(), tescShaderModule.get(), teseShaderModule.get(), geomShaderModule.get(), fragShaderModule2.get(), renderPassHandle, 0u, &vertexInputStateParams, &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL, DE_NULL, pipelineDynamicState, pPipelineRenderingCreateInfo);
456	const auto					pipeline3				= makeGraphicsPipeline(vk, device, pipelineLayout.get(), vertShaderModule3.get(), tescShaderModule.get(), teseShaderModule.get(), geomShaderModule.get(), fragShaderModule3.get(), renderPassHandle, 0u, &vertexInputStateParams, &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL, DE_NULL, pipelineDynamicState, pPipelineRenderingCreateInfo);
457	const auto					computePipeline			= vk::makeComputePipeline(vk, device, computePipelineLayout.get(), compShaderModule.get());
458
459	const vk::VkClearValue		clearValue				= vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
460	vk::VkImageMemoryBarrier	initialBarrier			= vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
461
462	const vk::VkDeviceSize				bufferSize		= 64;
463	de::MovePtr<vk::BufferWithMemory>	buffer			= de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
464		vk, device, alloc, vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), vk::MemoryRequirement::HostVisible));
465
466	vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
467
468	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0, DE_NULL,
469		0, DE_NULL, 1, &initialBarrier);
470
471	if (m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT)
472	{
473		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
474	}
475
476	if (m_params.testType != COMPUTE_SHADER_OBJECT_MIN_PIPELINE && m_params.testType != SHADER_OBJECT_COMPUTE_PIPELINE)
477		vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
478
479	vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, false, !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
480	vk::bindNullTaskMeshShaders(vk, *cmdBuffer, m_context.getMeshShaderFeaturesEXT());
481
482	vk::VkDeviceSize offset = 0u;
483	vk::VkDeviceSize stride = 16u;
484	vk.cmdBindVertexBuffers2(*cmdBuffer, 0u, 1u, &**buffer, &offset, &bufferSize, &stride);
485
486	if (m_params.testType == SHADER_OBJECT)
487	{
488		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1, taskSupported, meshSupported);
489		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
490	}
491	else if (m_params.testType == MAX_PIPELINE)
492	{
493		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
494		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
495	}
496	else if (m_params.testType == MAX_PIPELINE_SHADER_OBJECT_MAX_PIPELINE)
497	{
498		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
499		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
500
501		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader2, *tescShader, *teseShader, *geomShader, *fragShader2, taskSupported, meshSupported);
502		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
503
504		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline3);
505		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
506	}
507	else if (m_params.testType == SHADER_OBJECT_MAX_PIPELINE_SHADER_OBJECT)
508	{
509		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1, taskSupported, meshSupported);
510		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
511
512		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline2);
513		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
514
515		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader3, *tescShader, *teseShader, *geomShader, *fragShader3, taskSupported, meshSupported);
516		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
517	}
518	else if (m_params.testType == MIN_PIPELINE_SHADER_OBJECT)
519	{
520		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
521		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
522
523		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader2, *tescShader, *teseShader, *geomShader, *fragShader2, taskSupported, meshSupported);
524		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
525	}
526	else if (m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT)
527	{
528		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1, taskSupported, meshSupported);
529		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
530	}
531	else if (m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN)
532	{
533		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
534		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1, taskSupported, meshSupported);
535		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
536	}
537	else if (m_params.testType == SHADER_OBJECT_MIN_PIPELINE)
538	{
539		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1, taskSupported, meshSupported);
540		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
541
542		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline2);
543		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
544	}
545	else if (m_params.testType == COMPUTE_SHADER_OBJECT_MIN_PIPELINE)
546	{
547		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1, &descriptorSet.get(), 0, DE_NULL);
548
549		vk::VkShaderStageFlagBits stages[] = { vk::VK_SHADER_STAGE_COMPUTE_BIT  };
550		vk.cmdBindShadersEXT(*cmdBuffer, 1, stages, &*compShader);
551		vk.cmdDispatch(*cmdBuffer, 4, 1, 1);
552
553		vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
554		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
555		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
556		vk::endRendering(vk, *cmdBuffer);
557	}
558	else if (m_params.testType == SHADER_OBJECT_COMPUTE_PIPELINE)
559	{
560		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1, &descriptorSet.get(), 0, DE_NULL);
561
562		vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
563		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1, taskSupported, meshSupported);
564		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
565		vk::endRendering(vk, *cmdBuffer);
566
567		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
568		vk.cmdDispatch(*cmdBuffer, 4, 1, 1);
569	}
570
571	if (m_params.testType != COMPUTE_SHADER_OBJECT_MIN_PIPELINE && m_params.testType != SHADER_OBJECT_COMPUTE_PIPELINE)
572		vk::endRendering(vk, *cmdBuffer);
573
574	vk::endCommandBuffer(vk, *cmdBuffer);
575
576	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
577
578	const vk::VkBufferImageCopy	copyRegion =
579	{
580		0u,																		// VkDeviceSize				bufferOffset;
581		0u,																		// deUint32					bufferRowLength;
582		0u,																		// deUint32					bufferImageHeight;
583		{
584			vk::VK_IMAGE_ASPECT_COLOR_BIT,										// VkImageAspectFlags		aspect;
585			0u,																	// deUint32					mipLevel;
586			0u,																	// deUint32					baseArrayLayer;
587			1u,																	// deUint32					layerCount;
588		},																		// VkImageSubresourceLayers	imageSubresource;
589		{ 0, 0, 0 },															// VkOffset3D				imageOffset;
590		{renderArea.extent.width, renderArea.extent.height, 1}					// VkExtent3D				imageExtent;
591	};
592
593	vk::beginCommandBuffer(vk, *copyCmdBuffer, 0u);
594	vk.cmdCopyImageToBuffer(*copyCmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, &copyRegion);
595	vk::endCommandBuffer(vk, *copyCmdBuffer);
596	submitCommandsAndWait(vk, device, queue, copyCmdBuffer.get());
597
598	if (!verifyImage(colorOutputBuffer, getDrawCount()))
599		return tcu::TestStatus::fail("Fail");
600
601	if (m_params.testType == COMPUTE_SHADER_OBJECT_MIN_PIPELINE || m_params.testType == SHADER_OBJECT_COMPUTE_PIPELINE)
602	{
603		const vk::Allocation& outputBufferAllocation = outputBuffer.getAllocation();
604		invalidateAlloc(vk, device, outputBufferAllocation);
605
606		const deUint32* bufferPtr = static_cast<deUint32*>(outputBufferAllocation.getHostPtr());
607
608		for (deUint32 i = 0; i < 4; ++i)
609		{
610			if (bufferPtr[i] != i)
611				return tcu::TestStatus::fail("Fail");
612		}
613	}
614
615	return tcu::TestStatus::pass("Pass");
616}
617
618bool ShaderObjectPipelineInteractionInstance::verifyImage (de::MovePtr<vk::BufferWithMemory>& outputBuffer, deUint32 drawCount)
619{
620	tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(vk::mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM), renderArea.extent.width, renderArea.extent.height, 1, (const void*)outputBuffer->getAllocation().getHostPtr());
621
622	const tcu::Vec4			red			= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
623	const tcu::Vec4			green		= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
624	const tcu::Vec4			blue		= tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
625	const deInt32			width		= resultBuffer.getWidth();
626	const deInt32			height		= resultBuffer.getHeight();
627
628	for (deInt32 j = 0; j < height; ++j)
629	{
630		for (deInt32 i = 0; i < width; ++i)
631		{
632			const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
633			if (i < width / 2 && j < height / 2 && drawCount > 0)
634			{
635				if (color != red)
636					return false;
637			}
638			else if (i >= width / 2 && j < height / 2 && drawCount > 1)
639			{
640				if (color != green)
641					return false;
642			}
643			else if (i < width / 2 && j >= height / 2 && drawCount > 2)
644			{
645				if (color != blue)
646					return false;
647			}
648		}
649	}
650
651	return true;
652}
653
654class ShaderObjectPipelineInteractionCase : public vkt::TestCase
655{
656public:
657					ShaderObjectPipelineInteractionCase		(tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
658															: vkt::TestCase		(testCtx, name)
659															, m_params			(params)
660															{}
661	virtual			~ShaderObjectPipelineInteractionCase	(void) {}
662
663	void			checkSupport				(vkt::Context& context) const override;
664	virtual void	initPrograms				(vk::SourceCollections& programCollection) const override;
665	TestInstance*	createInstance				(Context& context) const override { return new ShaderObjectPipelineInteractionInstance(context, m_params); }
666private:
667	TestParams m_params;
668};
669
670void ShaderObjectPipelineInteractionCase::initPrograms (vk::SourceCollections& programCollection) const
671{
672	std::stringstream vert1, vert2, vert3;
673	std::stringstream geom;
674	std::stringstream tesc;
675	std::stringstream tese;
676	std::stringstream frag1, frag2, frag3;
677	std::stringstream comp;
678
679	vert1
680		<< "#version 450\n"
681		<< "void main() {\n"
682		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
683		<< "    gl_Position = vec4(pos * 0.5f - vec2(0.5f, 0.5f), 0.0f, 1.0f);\n"
684		<< "}\n";
685	vert2
686		<< "#version 450\n"
687		<< "void main() {\n"
688		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
689		<< "    gl_Position = vec4(pos * 0.5f - vec2(0.0f, 0.5f), 0.0f, 1.0f);\n"
690		<< "}\n";
691	vert3
692		<< "#version 450\n"
693		<< "void main() {\n"
694		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
695		<< "    gl_Position = vec4(pos * 0.5f - vec2(0.5f, 0.0f), 0.0f, 1.0f);\n"
696		<< "}\n";
697
698	tesc
699		<< "#version 450\n"
700		<< "\n"
701		<< "layout(vertices = 4) out;\n"
702		<< "\n"
703		<< "void main (void)\n"
704		<< "{\n"
705		<< "    if (gl_InvocationID == 0) {\n"
706		<< "		gl_TessLevelInner[0] = 1.0;\n"
707		<< "		gl_TessLevelInner[1] = 1.0;\n"
708		<< "		gl_TessLevelOuter[0] = 1.0;\n"
709		<< "		gl_TessLevelOuter[1] = 1.0;\n"
710		<< "		gl_TessLevelOuter[2] = 1.0;\n"
711		<< "		gl_TessLevelOuter[3] = 1.0;\n"
712		<< "	}\n"
713		<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
714		<< "}\n";
715
716	tese
717		<< "#version 450\n"
718		<< "\n"
719		<< "layout(quads, equal_spacing) in;\n"
720		<< "\n"
721		<< "void main (void)\n"
722		<< "{\n"
723		<< "	float u = gl_TessCoord.x;\n"
724		<< "	float v = gl_TessCoord.y;\n"
725		<< "	float omu = 1.0f - u;\n"
726		<< "	float omv = 1.0f - v;\n"
727		<< "	gl_Position = omu * omv * gl_in[0].gl_Position + u * omv * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position + omu * v * gl_in[1].gl_Position;\n"
728		<< "	gl_Position.x *= 2.0f;\n"
729		<< "}\n";
730
731	geom
732		<< "#version 450\n"
733		<< "layout(triangles) in;\n"
734		<< "layout(triangle_strip, max_vertices = 4) out;\n"
735		<< "\n"
736		<< "void main(void)\n"
737		<< "{\n"
738		<< "    gl_Position = gl_in[0].gl_Position;\n"
739		<< "	gl_Position.y *= 2.0f;\n"
740		<< "    EmitVertex();\n"
741		<< "    gl_Position = gl_in[1].gl_Position;\n"
742		<< "	gl_Position.y *= 2.0f;\n"
743		<< "    EmitVertex();\n"
744		<< "    gl_Position = gl_in[2].gl_Position;\n"
745		<< "	gl_Position.y *= 2.0f;\n"
746		<< "    EmitVertex();\n"
747		<< "    EndPrimitive();\n"
748		<< "}\n";
749
750	frag1
751		<< "#version 450\n"
752		<< "layout (location=0) out vec4 outColor;\n"
753		<< "void main() {\n"
754		<< "    outColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
755		<< "}\n";
756	frag2
757		<< "#version 450\n"
758		<< "layout (location=0) out vec4 outColor;\n"
759		<< "void main() {\n"
760		<< "    outColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
761		<< "}\n";
762	frag3
763		<< "#version 450\n"
764		<< "layout (location=0) out vec4 outColor;\n"
765		<< "void main() {\n"
766		<< "    outColor = vec4(0.0f, 0.0f, 1.0f, 1.0f);\n"
767		<< "}\n";
768
769	comp
770		<< "#version 450\n"
771		<< "layout(local_size_x=16, local_size_x=1, local_size_x=1) in;\n"
772		<< "layout(binding = 0) buffer Output {\n"
773		<< "    uint values[16];\n"
774		<< "} buffer_out;\n\n"
775		<< "void main() {\n"
776		<< "    buffer_out.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n"
777		<< "}\n";
778
779	programCollection.glslSources.add("vert1") << glu::VertexSource(vert1.str());
780	programCollection.glslSources.add("vert2") << glu::VertexSource(vert2.str());
781	programCollection.glslSources.add("vert3") << glu::VertexSource(vert3.str());
782	programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
783	programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
784	programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
785	programCollection.glslSources.add("frag1") << glu::FragmentSource(frag1.str());
786	programCollection.glslSources.add("frag2") << glu::FragmentSource(frag2.str());
787	programCollection.glslSources.add("frag3") << glu::FragmentSource(frag3.str());
788	programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
789}
790
791void ShaderObjectPipelineInteractionCase::checkSupport (Context& context) const
792{
793	context.requireDeviceFunctionality("VK_EXT_shader_object");
794
795	context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
796	context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
797}
798
799
800class ShaderObjectStageBindingInstance : public vkt::TestInstance
801{
802public:
803							ShaderObjectStageBindingInstance			(Context& context, const StageTestParams& params)
804																		: vkt::TestInstance	(context)
805																		, m_params			(params)
806																		{}
807	virtual					~ShaderObjectStageBindingInstance			(void) {}
808
809	tcu::TestStatus			iterate										(void) override;
810private:
811	bool					verifyImage									(de::MovePtr<vk::BufferWithMemory>& outputBuffer);
812	StageTestParams			m_params;
813
814	const vk::VkFormat		colorAttachmentFormat	= vk::VK_FORMAT_R8G8B8A8_UNORM;
815	const vk::VkRect2D		renderArea				= { {0u, 0u, }, {32u, 32u, } };
816};
817
818tcu::TestStatus ShaderObjectStageBindingInstance::iterate (void)
819{
820	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
821	const vk::VkDevice					device						= m_context.getDevice();
822	const vk::VkQueue					queue						= m_context.getUniversalQueue();
823	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
824	auto&								alloc						= m_context.getDefaultAllocator();
825	const auto							deviceExtensions			= vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
826	const bool							tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
827	const bool							geometrySupported			= m_context.getDeviceFeatures().geometryShader;
828	const bool							taskSupported				= m_context.getMeshShaderFeatures().taskShader;
829	const bool							meshSupported				= m_context.getMeshShaderFeatures().meshShader;
830
831	const auto							subresourceRange			= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
832
833	const vk::VkImageCreateInfo			createInfo					=
834	{
835		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType
836		DE_NULL,																		// const void*				pNext
837		0u,																				// VkImageCreateFlags		flags
838		vk::VK_IMAGE_TYPE_2D,															// VkImageType				imageType
839		colorAttachmentFormat,															// VkFormat					format
840		{ renderArea.extent.width, renderArea.extent.height, 1 },						// VkExtent3D				extent
841		1u,																				// uint32_t					mipLevels
842		1u,																				// uint32_t					arrayLayers
843		vk::VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples
844		vk::VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling
845		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
846		vk::VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode
847		0,																				// uint32_t					queueFamilyIndexCount
848		DE_NULL,																		// const uint32_t*			pQueueFamilyIndices
849		vk::VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout
850	};
851
852	de::MovePtr<vk::ImageWithMemory>	image						= de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
853	const auto							imageView					= vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
854
855	const vk::VkDeviceSize				colorOutputBufferSize		= renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
856	de::MovePtr<vk::BufferWithMemory>	colorOutputBuffer			= de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
857		vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
858
859	const vk::VkCommandPoolCreateInfo	cmdPoolInfo =
860	{
861		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// sType
862		DE_NULL,												// pNext
863		vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// flags
864		queueFamilyIndex,										// queuefamilyindex
865	};
866
867	const vk::Move<vk::VkCommandPool>	cmdPool					(createCommandPool(vk, device, &cmdPoolInfo));
868	const vk::Move<vk::VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
869	const vk::Move<vk::VkCommandBuffer>	copyCmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
870
871	const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
872		vk::DescriptorSetLayoutBuilder()
873		.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_ALL_GRAPHICS)
874		.build(vk, device));
875
876	const vk::Unique<vk::VkDescriptorPool> descriptorPool(
877		vk::DescriptorPoolBuilder()
878		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
879		.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
880
881	const auto					topology			= m_params.tessShader ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
882
883	const auto					pipelineLayout		= makePipelineLayout(vk, device, descriptorSetLayout.get());
884	const auto					emptyPipelineLayout	= makePipelineLayout(vk, device);
885
886	const auto&					binaries			= m_context.getBinaryCollection();
887	const auto&					vert				= binaries.get("vert");
888	const auto&					tesc				= binaries.get("tesc");
889	const auto&					tese				= binaries.get("tese");
890	const auto&					geom				= binaries.get("geom");
891	const auto&					frag				= binaries.get("frag");
892
893	const auto&					pipeline_vert		= binaries.get("pipeline_vert");
894	const auto&					pipeline_tesc		= binaries.get("pipeline_tesc");
895	const auto&					pipeline_tese		= binaries.get("pipeline_tese");
896	const auto&					pipeline_geom		= binaries.get("pipeline_geom");
897	const auto&					pipeline_frag		= binaries.get("pipeline_frag");
898
899	vk::VkDescriptorSetLayout	layout				= descriptorSetLayout.get();
900
901	vk::VkShaderCreateInfoEXT	vertCreateInfo		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert, tessellationSupported, geometrySupported, &layout);
902	vk::VkShaderCreateInfoEXT	tescCreateInfo		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, tesc, tessellationSupported, geometrySupported, &layout);
903	vk::VkShaderCreateInfoEXT	teseCreateInfo		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, tese, tessellationSupported, geometrySupported, &layout);
904	vk::VkShaderCreateInfoEXT	geomCreateInfo		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, geom, tessellationSupported, geometrySupported, &layout);
905	vk::VkShaderCreateInfoEXT	fragCreateInfo		= vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag, tessellationSupported, geometrySupported, &layout);
906
907	vk::Move<vk::VkShaderEXT>	vertShader			= vk::createShader(vk, device, vertCreateInfo);
908	vk::Move<vk::VkShaderEXT>	tescShader;
909	vk::Move<vk::VkShaderEXT>	teseShader;
910	vk::Move<vk::VkShaderEXT>	geomShader;
911	vk::Move<vk::VkShaderEXT>	fragShader			= vk::createShader(vk, device, fragCreateInfo);
912
913	vk::Move<vk::VkShaderModule>	vertShaderModule = createShaderModule(vk, device, pipeline_vert);
914	vk::Move<vk::VkShaderModule>	tescShaderModule;
915	vk::Move<vk::VkShaderModule>	teseShaderModule;
916	vk::Move<vk::VkShaderModule>	geomShaderModule;
917	vk::Move<vk::VkShaderModule>	fragShaderModule = createShaderModule(vk, device, pipeline_frag);
918
919	if (m_params.tessShader)
920	{
921		tescShader = vk::createShader(vk, device, tescCreateInfo);
922		teseShader = vk::createShader(vk, device, teseCreateInfo);
923
924		tescShaderModule = createShaderModule(vk, device, pipeline_tesc);
925		teseShaderModule = createShaderModule(vk, device, pipeline_tese);
926	}
927	if (m_params.geomShader)
928	{
929		geomShader = vk::createShader(vk, device, geomCreateInfo);
930
931		geomShaderModule = createShaderModule(vk, device, pipeline_geom);
932	}
933
934	const vk::VkPipelineVertexInputStateCreateInfo		vertexInputStateParams =
935	{
936		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
937		DE_NULL,														// const void*								pNext;
938		0u,																// VkPipelineVertexInputStateCreateFlags	flags;
939		0u,																// deUint32									vertexBindingDescriptionCount;
940		DE_NULL,														// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
941		0u,																// deUint32									vertexAttributeDescriptionCount;
942		DE_NULL															// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
943	};
944
945	const vk::VkPipelineTessellationStateCreateInfo		tessStateCreateInfo =
946	{
947		vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
948		DE_NULL,														//	const void*								pNext;
949		0u,																//	VkPipelineTessellationStateCreateFlags	flags;
950		4u,																//	uint32_t								patchControlPoints;
951	};
952
953	const vk::VkPipelineInputAssemblyStateCreateInfo	pipelineInputAssemblyStateInfo =
954	{
955		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
956		DE_NULL,															// const void*                                 pNext;
957		(vk::VkPipelineInputAssemblyStateCreateFlags)0u,					// VkPipelineInputAssemblyStateCreateFlags     flags;
958		topology,															// VkPrimitiveTopology                         topology;
959		VK_FALSE,															// VkBool32                                    primitiveRestartEnable;
960	};
961
962	vk::VkPipelineRenderingCreateInfo					pipelineRenderingCreateInfo =
963	{
964		vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,	// VkStructureType	sType
965		DE_NULL,												// const void*		pNext
966		0u,														// uint32_t			viewMask
967		1u,														// uint32_t			colorAttachmentCount
968		&colorAttachmentFormat,									// const VkFormat*	pColorAttachmentFormats
969		vk::VK_FORMAT_UNDEFINED,								// VkFormat			depthAttachmentFormat
970		vk::VK_FORMAT_UNDEFINED,								// VkFormat			stencilAttachmentFormat
971	};
972
973	const vk::VkViewport								viewport				= vk::makeViewport((float)renderArea.extent.width, 0.0f, (float)renderArea.extent.width, (float)renderArea.extent.height, 0.0f, 1.0f);
974	const vk::VkRect2D									scissor					= vk::makeRect2D(renderArea.extent);
975
976	const vk::VkPipelineViewportStateCreateInfo			viewportStateCreateInfo =
977	{
978		vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType
979		DE_NULL,													// const void*                                 pNext
980		(vk::VkPipelineViewportStateCreateFlags)0u,					// VkPipelineViewportStateCreateFlags          flags
981		1u,															// deUint32                                    viewportCount
982		&viewport,													// const VkViewport*                           pViewports
983		1u,															// deUint32                                    scissorCount
984		&scissor													// const VkRect2D*                             pScissors
985	};
986
987	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, DE_NULL, &pipelineRenderingCreateInfo);
988
989
990	const vk::VkDeviceSize					bufferSizeBytes = sizeof(deUint32) * 4;
991
992	const vk::Unique<vk::VkDescriptorSet>	descriptorSet	(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
993	const vk::BufferWithMemory				outputBuffer	(vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
994
995	const vk::VkDescriptorBufferInfo		descriptorInfo	= vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
996	vk::DescriptorSetUpdateBuilder()
997		.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
998		.update(vk, device);
999
1000	const vk::VkClearValue					clearValue		= vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
1001	vk::VkImageMemoryBarrier				initialBarrier	= vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
1002
1003	vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
1004
1005	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0, DE_NULL,
1006		0, DE_NULL, 1, &initialBarrier);
1007
1008	vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
1009
1010	vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1011	vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
1012
1013	vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0, 1, &descriptorSet.get(), 0, DE_NULL);
1014	vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, topology, false, !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
1015
1016	vk::bindGraphicsShaders(vk, *cmdBuffer,
1017		(m_params.vertShader) ? *vertShader : VK_NULL_HANDLE,
1018		(m_params.tessShader) ? *tescShader : VK_NULL_HANDLE,
1019		(m_params.tessShader) ? *teseShader : VK_NULL_HANDLE,
1020		(m_params.geomShader) ? *geomShader : VK_NULL_HANDLE,
1021		(m_params.fragShader) ? *fragShader : VK_NULL_HANDLE,
1022		taskSupported,
1023		meshSupported);
1024
1025	vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
1026
1027	vk::endRendering(vk, *cmdBuffer);
1028
1029	vk::endCommandBuffer(vk, *cmdBuffer);
1030
1031	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1032
1033	if (m_params.fragShader)
1034	{
1035		const vk::VkBufferImageCopy	copyRegion =
1036		{
1037			0u,																		// VkDeviceSize				bufferOffset;
1038			0u,																		// deUint32					bufferRowLength;
1039			0u,																		// deUint32					bufferImageHeight;
1040			{
1041				vk::VK_IMAGE_ASPECT_COLOR_BIT,										// VkImageAspectFlags		aspect;
1042				0u,																	// deUint32					mipLevel;
1043				0u,																	// deUint32					baseArrayLayer;
1044				1u,																	// deUint32					layerCount;
1045			},																		// VkImageSubresourceLayers	imageSubresource;
1046			{ 0, 0, 0 },															// VkOffset3D				imageOffset;
1047			{renderArea.extent.width, renderArea.extent.height, 1}					// VkExtent3D				imageExtent;
1048		};
1049
1050		vk::beginCommandBuffer(vk, *copyCmdBuffer, 0u);
1051		vk.cmdCopyImageToBuffer(*copyCmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, &copyRegion);
1052		vk::endCommandBuffer(vk, *copyCmdBuffer);
1053		submitCommandsAndWait(vk, device, queue, copyCmdBuffer.get());
1054
1055		if (!verifyImage(colorOutputBuffer))
1056			return tcu::TestStatus::fail("Fail");
1057	}
1058
1059	const vk::Allocation& outputBufferAllocation = outputBuffer.getAllocation();
1060	invalidateAlloc(vk, device, outputBufferAllocation);
1061
1062	const deUint32* bufferPtr = static_cast<deUint32*>(outputBufferAllocation.getHostPtr());
1063
1064	if (m_params.vertShader && bufferPtr[0] != 1u)
1065		return tcu::TestStatus::fail("Fail");
1066	if (m_params.tessShader && bufferPtr[1] != 2u)
1067		return tcu::TestStatus::fail("Fail");
1068	if (m_params.geomShader && bufferPtr[2] != 3u)
1069		return tcu::TestStatus::fail("Fail");
1070
1071	return tcu::TestStatus::pass("Pass");
1072}
1073
1074bool ShaderObjectStageBindingInstance::verifyImage (de::MovePtr<vk::BufferWithMemory>& outputBuffer)
1075{
1076	tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(vk::mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM), renderArea.extent.width, renderArea.extent.height, 1, (const void*)outputBuffer->getAllocation().getHostPtr());
1077
1078	const tcu::Vec4			black		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1079	const tcu::Vec4			white		= tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1080	const deInt32			width		= resultBuffer.getWidth();
1081	const deInt32			height		= resultBuffer.getHeight();
1082
1083	const deInt32			xOffset		= m_params.tessShader ? 4 : 8;
1084	const deInt32			yOffset		= m_params.geomShader ? 4 : 8;
1085
1086	for (deInt32 j = 0; j < height; ++j)
1087	{
1088		for (deInt32 i = 0; i < width; ++i)
1089		{
1090			const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
1091			if (i >= xOffset && i < width - xOffset && j >= yOffset && j < height - yOffset)
1092			{
1093				if (color != white)
1094					return false;
1095			}
1096			else
1097			{
1098				if (color != black)
1099					return false;
1100			}
1101		}
1102	}
1103
1104	return true;
1105}
1106
1107class ShaderObjectStageBindingCase : public vkt::TestCase
1108{
1109public:
1110					ShaderObjectStageBindingCase			(tcu::TestContext& testCtx, const std::string& name, const StageTestParams& params)
1111															: vkt::TestCase		(testCtx, name)
1112															, m_params			(params)
1113															{}
1114	virtual			~ShaderObjectStageBindingCase			(void) {}
1115
1116	void			checkSupport							(vkt::Context& context) const override;
1117	virtual void	initPrograms							(vk::SourceCollections& programCollection) const override;
1118	TestInstance*	createInstance							(Context& context) const override { return new ShaderObjectStageBindingInstance(context, m_params); }
1119private:
1120	StageTestParams m_params;
1121};
1122
1123void ShaderObjectStageBindingCase::checkSupport (Context& context) const
1124{
1125	context.requireDeviceFunctionality("VK_EXT_shader_object");
1126
1127	if (m_params.tessShader)
1128		context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1129
1130	if (m_params.geomShader)
1131		context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1132}
1133
1134void ShaderObjectStageBindingCase::initPrograms(vk::SourceCollections& programCollection) const
1135{
1136	std::stringstream vert;
1137	std::stringstream geom;
1138	std::stringstream tesc;
1139	std::stringstream tese;
1140	std::stringstream frag;
1141
1142	std::stringstream pipeline_vert;
1143	std::stringstream pipeline_geom;
1144	std::stringstream pipeline_tesc;
1145	std::stringstream pipeline_tese;
1146	std::stringstream pipeline_frag;
1147
1148	vert
1149		<< "#version 450\n"
1150		<< "layout(set = 0, binding = 0) buffer Output {\n"
1151		<< "    uint values[4];\n"
1152		<< "} buffer_out;\n\n"
1153		<< "void main() {\n"
1154		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
1155		<< "    gl_Position = vec4(pos - 0.5f, 0.0f, 1.0f);\n"
1156		<< "	if (gl_VertexIndex == 0u)\n"
1157		<< "		buffer_out.values[0] = 1u;\n"
1158		<< "}\n";
1159
1160	tesc
1161		<< "#version 450\n"
1162		<< "\n"
1163		<< "layout(vertices = 4) out;\n"
1164		<< "layout(set = 0, binding = 0) buffer Output {\n"
1165		<< "    uint values[4];\n"
1166		<< "} buffer_out;\n\n"
1167		<< "\n"
1168		<< "void main (void)\n"
1169		<< "{\n"
1170		<< "    if (gl_InvocationID == 0) {\n"
1171		<< "		gl_TessLevelInner[0] = 1.0;\n"
1172		<< "		gl_TessLevelInner[1] = 1.0;\n"
1173		<< "		gl_TessLevelOuter[0] = 1.0;\n"
1174		<< "		gl_TessLevelOuter[1] = 1.0;\n"
1175		<< "		gl_TessLevelOuter[2] = 1.0;\n"
1176		<< "		gl_TessLevelOuter[3] = 1.0;\n"
1177		<< "		buffer_out.values[1] = 2u;\n"
1178		<< "	}\n"
1179		<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1180		<< "}\n";
1181
1182	tese
1183		<< "#version 450\n"
1184		<< "\n"
1185		<< "layout(quads, equal_spacing) in;\n"
1186		<< "\n"
1187		<< "void main (void)\n"
1188		<< "{\n"
1189		<< "	float u = gl_TessCoord.x;\n"
1190		<< "	float v = gl_TessCoord.y;\n"
1191		<< "	float omu = 1.0f - u;\n"
1192		<< "	float omv = 1.0f - v;\n"
1193		<< "	gl_Position = omu * omv * gl_in[0].gl_Position + u * omv * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position + omu * v * gl_in[1].gl_Position;\n"
1194		<< "	gl_Position.x *= 1.5f;\n"
1195		<< "}\n";
1196
1197	geom
1198		<< "#version 450\n"
1199		<< "layout(triangles) in;\n"
1200		<< "layout(triangle_strip, max_vertices = 4) out;\n"
1201		<< "layout(set = 0, binding = 0) buffer Output {\n"
1202		<< "    uint values[4];\n"
1203		<< "} buffer_out;\n\n"
1204		<< "\n"
1205		<< "void main(void)\n"
1206		<< "{\n"
1207		<< "    gl_Position = gl_in[0].gl_Position;\n"
1208		<< "	gl_Position.y *= 1.5f;\n"
1209		<< "    EmitVertex();\n"
1210		<< "    gl_Position = gl_in[1].gl_Position;\n"
1211		<< "	gl_Position.y *= 1.5f;\n"
1212		<< "    EmitVertex();\n"
1213		<< "    gl_Position = gl_in[2].gl_Position;\n"
1214		<< "	gl_Position.y *= 1.5f;\n"
1215		<< "    EmitVertex();\n"
1216		<< "    EndPrimitive();\n"
1217		<< "    if (gl_InvocationID == 0u)\n"
1218		<< "		buffer_out.values[2] = 3u;\n"
1219		<< "}\n";
1220
1221	frag
1222		<< "#version 450\n"
1223		<< "layout (location=0) out vec4 outColor;\n"
1224		<< "void main() {\n"
1225		<< "    outColor = vec4(1.0f);\n"
1226		<< "}\n";
1227
1228	pipeline_vert
1229		<< "#version 450\n"
1230		<< "void main() {\n"
1231		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
1232		<< "    gl_Position = vec4(pos - 0.5f, 0.0f, 1.0f);\n"
1233		<< "}\n";
1234
1235	pipeline_tesc
1236		<< "#version 450\n"
1237		<< "\n"
1238		<< "layout(vertices = 4) out;\n"
1239		<< "\n"
1240		<< "void main (void)\n"
1241		<< "{\n"
1242		<< "    if (gl_InvocationID == 0) {\n"
1243		<< "		gl_TessLevelInner[0] = 1.0;\n"
1244		<< "		gl_TessLevelInner[1] = 1.0;\n"
1245		<< "		gl_TessLevelOuter[0] = 1.0;\n"
1246		<< "		gl_TessLevelOuter[1] = 1.0;\n"
1247		<< "		gl_TessLevelOuter[2] = 1.0;\n"
1248		<< "		gl_TessLevelOuter[3] = 1.0;\n"
1249		<< "	}\n"
1250		<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1251		<< "}\n";
1252
1253	pipeline_tese
1254		<< "#version 450\n"
1255		<< "\n"
1256		<< "layout(quads, equal_spacing) in;\n"
1257		<< "\n"
1258		<< "void main (void)\n"
1259		<< "{\n"
1260		<< "	float u = gl_TessCoord.x;\n"
1261		<< "	float v = gl_TessCoord.y;\n"
1262		<< "	float omu = 1.0f - u;\n"
1263		<< "	float omv = 1.0f - v;\n"
1264		<< "	gl_Position = omu * omv * gl_in[0].gl_Position + u * omv * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position + omu * v * gl_in[1].gl_Position;\n"
1265		<< "	gl_Position.x *= 0.5f;\n"
1266		<< "	gl_Position.y *= 0.5f;\n"
1267		<< "}\n";
1268
1269	pipeline_geom
1270		<< "#version 450\n"
1271		<< "layout(triangles) in;\n"
1272		<< "layout(triangle_strip, max_vertices = 4) out;\n"
1273		<< "\n"
1274		<< "void main(void)\n"
1275		<< "{\n"
1276		<< "    gl_Position = gl_in[0].gl_Position;\n"
1277		<< "	gl_Position.x += 0.25f;\n"
1278		<< "	gl_Position.y += 0.25f;\n"
1279		<< "    EmitVertex();\n"
1280		<< "    gl_Position = gl_in[1].gl_Position;\n"
1281		<< "	gl_Position.x += 0.25f;\n"
1282		<< "	gl_Position.y += 0.25f;\n"
1283		<< "    EmitVertex();\n"
1284		<< "    gl_Position = gl_in[2].gl_Position;\n"
1285		<< "	gl_Position.x += 0.25f;\n"
1286		<< "	gl_Position.y += 0.25f;\n"
1287		<< "    EmitVertex();\n"
1288		<< "    EndPrimitive();\n"
1289		<< "}\n";
1290
1291	pipeline_frag
1292		<< "#version 450\n"
1293		<< "layout (location=0) out vec4 outColor;\n"
1294		<< "void main() {\n"
1295		<< "    outColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
1296		<< "}\n";
1297
1298	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
1299	programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
1300	programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
1301	programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
1302	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1303
1304	programCollection.glslSources.add("pipeline_vert") << glu::VertexSource(pipeline_vert.str());
1305	programCollection.glslSources.add("pipeline_tesc") << glu::TessellationControlSource(pipeline_tesc.str());
1306	programCollection.glslSources.add("pipeline_tese") << glu::TessellationEvaluationSource(pipeline_tese.str());
1307	programCollection.glslSources.add("pipeline_geom") << glu::GeometrySource(pipeline_geom.str());
1308	programCollection.glslSources.add("pipeline_frag") << glu::FragmentSource(pipeline_frag.str());
1309}
1310
1311}
1312
1313tcu::TestCaseGroup* createShaderObjectPipelineInteractionTests (tcu::TestContext& testCtx)
1314{
1315	de::MovePtr<tcu::TestCaseGroup> pipelineInteractionGroup(new tcu::TestCaseGroup(testCtx, "pipeline_interaction"));
1316
1317	const struct
1318	{
1319		TestType	testType;
1320		const char* name;
1321	} tests[] =
1322	{
1323		{ SHADER_OBJECT,									"shader_object"										},
1324		{ MAX_PIPELINE,										"max_pipeline"										},
1325		{ MAX_PIPELINE_SHADER_OBJECT_MAX_PIPELINE,			"max_pipeline_shader_object_max_pipeline"			},
1326		{ SHADER_OBJECT_MAX_PIPELINE_SHADER_OBJECT,			"shader_object_max_pipeline_shader_object"			},
1327		{ MIN_PIPELINE_SHADER_OBJECT,						"min_pipeline_shader_object"						},
1328		{ SHADER_OBJECT_MIN_PIPELINE,						"shader_object_min_pipeline"						},
1329		{ RENDER_PASS_PIPELINE_SHADER_OBJECT,				"render_pass_pipeline_shader_object"				},
1330		{ RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN,	"render_pass_pipeline_shader_object_after_begin"	},
1331		{ COMPUTE_SHADER_OBJECT_MIN_PIPELINE,				"compute_shader_object_min_pipeline"				},
1332		{ SHADER_OBJECT_COMPUTE_PIPELINE,					"shader_object_compute_pipeline"					},
1333	};
1334
1335	for (const auto& test : tests)
1336	{
1337		TestParams params;
1338		params.testType = test.testType;
1339
1340		pipelineInteractionGroup->addChild(new ShaderObjectPipelineInteractionCase(testCtx, test.name, params));
1341	}
1342
1343	const struct
1344	{
1345		StageTestParams	shaders;
1346		const char* name;
1347	} shaderBindTests[] =
1348	{
1349		{ { true, false, false, false },	"vert"	},
1350		{ { true, true, false, false },		"vert_tess"	},
1351		{ { true, false, true, false },		"vert_geom"	},
1352		{ { true, false, false, true },		"vert_frag"	},
1353		{ { true, true, true, false },		"vert_tess_geom"	},
1354		{ { true, true, false, true },		"vert_tess_frag"	},
1355		{ { true, false, true, true },		"vert_geom_frag"	},
1356		{ { true, true, true, true },		"vert_tess_geom_frag"	},
1357	};
1358
1359	for (const auto& shaderBindTest : shaderBindTests)
1360	{
1361		pipelineInteractionGroup->addChild(new ShaderObjectStageBindingCase(testCtx, shaderBindTest.name, shaderBindTest.shaders));
1362	}
1363
1364	return pipelineInteractionGroup.release();
1365}
1366
1367} // ShaderObject
1368} // vkt
1369