• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Binding Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktShaderObjectBindingTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkShaderObjectUtil.hpp"
30 #include "vktShaderObjectCreateUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkBufferWithMemory.hpp"
36 #include "vkObjUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkBarrierUtil.hpp"
39 #include "deMath.h"
40 #include "vktCustomInstancesDevices.hpp"
41 #include "tcuCommandLine.hpp"
42 #include "vkBuilderUtil.hpp"
43 
44 namespace vkt
45 {
46 namespace ShaderObject
47 {
48 
49 namespace
50 {
51 
52 enum TestType {
53 	PASSTHROUGH_GEOM,
54 	SWAP,
55 	DISABLED,
56 	UNBIND,
57 	DRAW_DISPATCH_DRAW,
58 	DISPATCH_DRAW_DISPATCH,
59 };
60 
61 struct BindingDrawParams {
62 	TestType testType;
63 	vk::VkShaderStageFlagBits stage;
64 	vk::VkShaderStageFlagBits unusedOutputs;
65 	vk::VkShaderStageFlagBits binaryStage;
66 	bool bindUnsupported;
67 	bool setStateAfter;
68 	bool unbindWithNullpShaders;
69 };
70 
71 struct MeshBindingDrawParams {
72 	vk::VkShaderStageFlagBits stage;
73 };
74 
75 struct BindingParams {
76 	bool useMeshShaders;
77 };
78 
79 class ShaderObjectBindingDrawInstance : public vkt::TestInstance
80 {
81 public:
ShaderObjectBindingDrawInstance(Context & context,const BindingDrawParams & params)82 								ShaderObjectBindingDrawInstance		(Context& context, const BindingDrawParams& params)
83 																	: vkt::TestInstance		(context)
84 																	, m_params				(params)
85 																	{}
~ShaderObjectBindingDrawInstance(void)86 	virtual						~ShaderObjectBindingDrawInstance	(void) {}
87 
88 	tcu::TestStatus				iterate								(void) override;
89 private:
90 	vk::Move<vk::VkShaderEXT>	createShader						(const vk::DeviceInterface& vk, const vk::VkDevice device, vk::VkShaderStageFlagBits stage, const std::string& name, const vk::VkDescriptorSetLayout* descriptorSetLayout = DE_NULL);
91 	void						createDevice						(void);
getDevice(void)92 	vk::VkDevice				getDevice							(void) { return (m_params.testType == DISABLED) ? m_customDevice.get() : m_context.getDevice(); }
93 	void						setDynamicStates					(vk::VkCommandBuffer cmdBuffer, bool tessShader);
94 
95 	BindingDrawParams				m_params;
96 	vk::Move<vk::VkDevice>			m_customDevice;
97 };
98 
createDevice(void)99 void ShaderObjectBindingDrawInstance::createDevice (void)
100 {
101 	if (m_params.testType != DISABLED)
102 		return;
103 
104 	const float										queuePriority		= 1.0f;
105 	const auto&										deviceExtensions	= m_context.getDeviceCreationExtensions();
106 	auto											features2			= m_context.getDeviceFeatures2();
107 
108 	if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
109 		features2.features.geometryShader = VK_FALSE;
110 	else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
111 		features2.features.tessellationShader = VK_FALSE;
112 
113 	vk::VkDeviceQueueCreateInfo						queueInfo =
114 	{
115 		vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,					// VkStructureType					sType;
116 		DE_NULL,													// const void*						pNext;
117 		0u,															// VkDeviceQueueCreateFlags			flags;
118 		0u,															// deUint32							queueFamilyIndex;
119 		1u,															// deUint32							queueCount;
120 		&queuePriority												// const float*						pQueuePriorities;
121 	};
122 
123 	const vk::VkDeviceCreateInfo					deviceInfo =
124 	{
125 		vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,						// VkStructureType					sType;
126 		&features2,														// const void*						pNext;
127 		(vk::VkDeviceCreateFlags)0,										// VkDeviceCreateFlags				flags;
128 		1u,																// uint32_t							queueCreateInfoCount;
129 		&queueInfo,														// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
130 		0u,																// uint32_t							enabledLayerCount;
131 		DE_NULL,														// const char* const*				ppEnabledLayerNames;
132 		deUint32(deviceExtensions.size()),								// uint32_t							enabledExtensionCount;
133 		(deviceExtensions.empty()) ? DE_NULL : deviceExtensions.data(),	// const char* const*				ppEnabledExtensionNames;
134 		DE_NULL															// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
135 	};
136 
137 	m_customDevice = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), m_context.getPlatformInterface(), m_context.getInstance(), m_context.getInstanceInterface(), m_context.getPhysicalDevice(), &deviceInfo);
138 }
139 
createShader(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::VkShaderStageFlagBits stage,const std::string & name,const vk::VkDescriptorSetLayout * descriptorSetLayout)140 vk::Move<vk::VkShaderEXT> ShaderObjectBindingDrawInstance::createShader (const vk::DeviceInterface& vk, const vk::VkDevice device, vk::VkShaderStageFlagBits stage, const std::string& name, const vk::VkDescriptorSetLayout* descriptorSetLayout)
141 {
142 	const auto&					binaries					= m_context.getBinaryCollection();
143 	const bool					tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
144 	const bool					geometrySupported			= m_context.getDeviceFeatures().geometryShader;
145 
146 	if (m_params.binaryStage == stage)
147 	{
148 		auto shaderCreateInfo = vk::makeShaderCreateInfo(stage, binaries.get(name), tessellationSupported, geometrySupported, descriptorSetLayout);
149 		const auto shader = vk::createShader(vk, device, shaderCreateInfo);
150 
151 		size_t dataSize;
152 		vk.getShaderBinaryDataEXT(device, *shader, &dataSize, DE_NULL);
153 		std::vector<deUint8> data(dataSize);
154 		vk.getShaderBinaryDataEXT(device, *shader, &dataSize, data.data());
155 
156 		shaderCreateInfo.codeType = vk::VK_SHADER_CODE_TYPE_BINARY_EXT;
157 		shaderCreateInfo.codeSize = dataSize;
158 		shaderCreateInfo.pCode = data.data();
159 
160 		return vk::createShader(vk, device, shaderCreateInfo);
161 	}
162 
163 	return vk::createShader(vk, device, vk::makeShaderCreateInfo(stage, binaries.get(name), tessellationSupported, geometrySupported, descriptorSetLayout));
164 }
165 
setDynamicStates(vk::VkCommandBuffer cmdBuffer,bool tessShader)166 void ShaderObjectBindingDrawInstance::setDynamicStates (vk::VkCommandBuffer cmdBuffer, bool tessShader)
167 {
168 	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
169 	const auto							deviceExtensions			= vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
170 
171 	const vk::VkPrimitiveTopology		topology					= tessShader ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
172 
173 	vk::setDefaultShaderObjectDynamicStates(vk, cmdBuffer, deviceExtensions, topology, false);
174 
175 	vk::VkBool32 colorBlendEnable = VK_TRUE;
176 	vk.cmdSetColorBlendEnableEXT(cmdBuffer, 0u, 1u, &colorBlendEnable);
177 	vk::VkColorBlendEquationEXT		colorBlendEquation = {
178 		vk::VK_BLEND_FACTOR_ONE,				// VkBlendFactor	srcColorBlendFactor;
179 		vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,// VkBlendFactor	dstColorBlendFactor;
180 		vk::VK_BLEND_OP_ADD,					// VkBlendOp		colorBlendOp;
181 		vk::VK_BLEND_FACTOR_ONE,				// VkBlendFactor	srcAlphaBlendFactor;
182 		vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,// VkBlendFactor	dstAlphaBlendFactor;
183 		vk::VK_BLEND_OP_ADD,					// VkBlendOp		alphaBlendOp;
184 	};
185 	vk.cmdSetColorBlendEquationEXT(cmdBuffer, 0u, 1u, &colorBlendEquation);
186 }
187 
iterate(void)188 tcu::TestStatus ShaderObjectBindingDrawInstance::iterate (void)
189 {
190 	const vk::VkInstance				instance					= m_context.getInstance();
191 	const vk::InstanceDriver			instanceDriver				(m_context.getPlatformInterface(), instance);
192 	createDevice();
193 	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
194 	const vk::VkDevice					device						= getDevice();
195 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
196 	const vk::VkQueue					queue						= getDeviceQueue(m_context.getDeviceInterface(), device, queueFamilyIndex, 0u);
197 	auto								alloctor					= de::MovePtr<vk::Allocator>(new vk::SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(instanceDriver, m_context.getPhysicalDevice())));
198 	auto&								alloc						= *alloctor;
199 	tcu::TestLog&						log							= m_context.getTestContext().getLog();
200 
201 	const bool							tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
202 	const bool							geometrySupported			= m_context.getDeviceFeatures().geometryShader;
203 	const bool							taskSupported				= m_context.getMeshShaderFeatures().taskShader;
204 	const bool							meshSupported				= m_context.getMeshShaderFeatures().meshShader;
205 
206 	vk::VkFormat						colorAttachmentFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
207 	const auto							subresourceRange			= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
208 	const auto							subresourceLayers			= vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
209 	const vk::VkRect2D					renderArea					= vk::makeRect2D(0, 0, 32, 32);
210 	vk::VkExtent3D						extent						= { renderArea.extent.width, renderArea.extent.height, 1};
211 
212 	const vk::VkImageCreateInfo	createInfo =
213 	{
214 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
215 		DE_NULL,									// const void*				pNext
216 		0u,											// VkImageCreateFlags		flags
217 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
218 		colorAttachmentFormat,						// VkFormat					format
219 		{ 32, 32, 1 },								// VkExtent3D				extent
220 		1u,											// uint32_t					mipLevels
221 		1u,											// uint32_t					arrayLayers
222 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
223 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
224 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
225 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
226 		0,											// uint32_t					queueFamilyIndexCount
227 		DE_NULL,									// const uint32_t*			pQueueFamilyIndices
228 		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
229 	};
230 
231 	de::MovePtr<vk::ImageWithMemory>	image					= de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
232 	const auto							imageView				= vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
233 
234 	const vk::VkDeviceSize				colorOutputBufferSize	= renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
235 	de::MovePtr<vk::BufferWithMemory>	colorOutputBuffer		= de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
236 		vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
237 
238 	const vk::VkDeviceSize				bufferSizeBytes				= sizeof(deUint32) * 16;
239 	const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
240 		vk::DescriptorSetLayoutBuilder()
241 		.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
242 		.build(vk, device));
243 
244 	const vk::Unique<vk::VkDescriptorPool>	descriptorPool(
245 		vk::DescriptorPoolBuilder()
246 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u)
247 		.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u));
248 
249 	const vk::Move<vk::VkCommandPool>	cmdPool		(vk::createCommandPool(vk, device, 0u, queueFamilyIndex));
250 	const vk::Move<vk::VkCommandBuffer>	cmdBuffer	(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
251 
252 	const vk::Unique<vk::VkDescriptorSet>	descriptorSet1	(vk::makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
253 	const vk::Unique<vk::VkDescriptorSet>	descriptorSet2	(vk::makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
254 	const vk::BufferWithMemory				outputBuffer1	(vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
255 	const vk::BufferWithMemory				outputBuffer2	(vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
256 
257 	const auto								computePipelineLayout	= makePipelineLayout(vk, device, descriptorSetLayout.get());
258 
259 	const vk::VkDescriptorBufferInfo		descriptorInfo1	= vk::makeDescriptorBufferInfo(*outputBuffer1, 0ull, bufferSizeBytes);
260 	const vk::VkDescriptorBufferInfo		descriptorInfo2	= vk::makeDescriptorBufferInfo(*outputBuffer2, 0ull, bufferSizeBytes);
261 	vk::DescriptorSetUpdateBuilder()
262 		.writeSingle(*descriptorSet1, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo1)
263 		.update(vk, device);
264 	vk::DescriptorSetUpdateBuilder()
265 		.writeSingle(*descriptorSet2, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo2)
266 		.update(vk, device);
267 
268 	vk::Move<vk::VkShaderEXT>			vertShader;
269 	vk::Move<vk::VkShaderEXT>			tescShader;
270 	vk::Move<vk::VkShaderEXT>			teseShader;
271 	vk::Move<vk::VkShaderEXT>			geomShader;
272 	vk::Move<vk::VkShaderEXT>			fragShader;
273 	vk::Move<vk::VkShaderEXT>			compShader;
274 	vk::Move<vk::VkShaderEXT>			passThroughGeomShader;
275 	vk::Move<vk::VkShaderEXT>			vertAltShader;
276 	vk::Move<vk::VkShaderEXT>			tescAltShader;
277 	vk::Move<vk::VkShaderEXT>			teseAltShader;
278 	vk::Move<vk::VkShaderEXT>			geomAltShader;
279 	vk::Move<vk::VkShaderEXT>			fragAltShader;
280 
281 	if (tessellationSupported && geometrySupported)
282 	{
283 		vertShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vert");
284 		vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAlt");
285 	}
286 	else if (tessellationSupported)
287 	{
288 		vertShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertNoGeom");
289 		vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAltNoGeom");
290 	}
291 	else if (geometrySupported)
292 	{
293 		vertShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertNoTess");
294 		vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAltNoTess");
295 	}
296 	else
297 	{
298 		vertShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertNoTessGeom");
299 		vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAltNoTessGeom");
300 	}
301 	if (tessellationSupported && (m_params.stage != vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_params.testType != DISABLED))
302 	{
303 		tescShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tesc");
304 		teseShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tese");
305 		tescAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tescAlt");
306 		teseAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "teseAlt");
307 	}
308 	if (geometrySupported && (m_params.stage != vk::VK_SHADER_STAGE_GEOMETRY_BIT || m_params.testType != DISABLED))
309 	{
310 		geomShader = createShader(vk, device, vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geom");
311 		geomAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geomAlt");
312 		passThroughGeomShader = createShader(vk, device, vk::VK_SHADER_STAGE_GEOMETRY_BIT, "passThroughGeom");
313 	}
314 	fragShader					= createShader(vk, device, vk::VK_SHADER_STAGE_FRAGMENT_BIT, "blendFrag");
315 	compShader					= createShader(vk, device, vk::VK_SHADER_STAGE_COMPUTE_BIT, "comp", &*descriptorSetLayout);
316 	fragAltShader				= createShader(vk, device, vk::VK_SHADER_STAGE_FRAGMENT_BIT, "fragAlt");
317 
318 	const vk::VkClearValue				clearValue = vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 0.0f });
319 	vk::beginCommandBuffer(vk, *cmdBuffer);
320 
321 	vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
322 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &preImageBarrier);
323 
324 	if (!m_params.setStateAfter)
325 		setDynamicStates(*cmdBuffer, tessellationSupported);
326 
327 	vk::VkBool32 colorBlendEnable = VK_TRUE;
328 	vk.cmdSetColorBlendEnableEXT(*cmdBuffer, 0u, 1u, &colorBlendEnable);
329 	vk::VkColorBlendEquationEXT		colorBlendEquation = {
330 		vk::VK_BLEND_FACTOR_ONE,				// VkBlendFactor	srcColorBlendFactor;
331 		vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,// VkBlendFactor	dstColorBlendFactor;
332 		vk::VK_BLEND_OP_ADD,					// VkBlendOp		colorBlendOp;
333 		vk::VK_BLEND_FACTOR_ONE,				// VkBlendFactor	srcAlphaBlendFactor;
334 		vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,// VkBlendFactor	dstAlphaBlendFactor;
335 		vk::VK_BLEND_OP_ADD,					// VkBlendOp		alphaBlendOp;
336 	};
337 	vk.cmdSetColorBlendEquationEXT(*cmdBuffer, 0u, 1u, &colorBlendEquation);
338 
339 	if (m_params.testType != DISPATCH_DRAW_DISPATCH)
340 		vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
341 
342 	vk::VkShaderEXT nullShader = VK_NULL_HANDLE;
343 
344 	if (m_params.testType == PASSTHROUGH_GEOM)
345 	{
346 		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *passThroughGeomShader, *fragShader, taskSupported, meshSupported);
347 		if (m_params.setStateAfter)
348 			setDynamicStates(*cmdBuffer, tessellationSupported);
349 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
350 		vk::VkShaderStageFlagBits geomStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
351 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &geomStage, &nullShader);
352 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
353 	}
354 	else if (m_params.testType == SWAP)
355 	{
356 		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader, taskSupported, meshSupported);
357 		if (m_params.setStateAfter)
358 			setDynamicStates(*cmdBuffer, tessellationSupported);
359 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
360 		vk::VkShaderEXT shader = VK_NULL_HANDLE;
361 		if (m_params.stage == vk::VK_SHADER_STAGE_VERTEX_BIT)
362 			shader = *vertAltShader;
363 		else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
364 			shader = *tescAltShader;
365 		else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
366 			shader = *teseAltShader;
367 		else if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
368 			shader = *geomAltShader;
369 		else if (m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
370 			shader = *fragAltShader;
371 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &shader);
372 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
373 	}
374 	else if (m_params.testType == DISABLED)
375 	{
376 		if (taskSupported) {
377 			vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
378 			vk::VkShaderEXT shader = VK_NULL_HANDLE;
379 			vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stage, &shader);
380 		}
381 		if (meshSupported) {
382 			vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_MESH_BIT_EXT;
383 			vk::VkShaderEXT shader = VK_NULL_HANDLE;
384 			vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stage, &shader);
385 		}
386 		if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
387 		{
388 			vk::VkShaderStageFlagBits stages[] = { vk::VK_SHADER_STAGE_VERTEX_BIT, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT };
389 			vk::VkShaderEXT shaders[] = { *vertShader, *tescShader, *teseShader, *fragShader };
390 			vk.cmdBindShadersEXT(*cmdBuffer, 4u, stages, shaders);
391 			if (m_params.bindUnsupported)
392 				vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &nullShader);
393 			if (m_params.setStateAfter)
394 				setDynamicStates(*cmdBuffer, tessellationSupported);
395 			vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
396 		}
397 		else
398 		{
399 			vk.cmdSetPrimitiveTopology(*cmdBuffer, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
400 			vk::VkShaderStageFlagBits stages[] = { vk::VK_SHADER_STAGE_VERTEX_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT };
401 			vk::VkShaderEXT shaders[] = { *vertShader, *geomShader, *fragShader };
402 			vk.cmdBindShadersEXT(*cmdBuffer, 3u, stages, shaders);
403 			if (m_params.bindUnsupported)
404 				vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &nullShader);
405 			if (m_params.setStateAfter)
406 				setDynamicStates(*cmdBuffer, tessellationSupported);
407 			vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
408 		}
409 	}
410 	else if (m_params.testType == UNBIND)
411 	{
412 		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader, taskSupported, meshSupported);
413 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
414 		if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
415 		{
416 			if (m_params.unbindWithNullpShaders)
417 				vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, DE_NULL);
418 			else
419 				vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &nullShader);
420 		}
421 		else
422 		{
423 			vk::VkShaderStageFlagBits stages[] = { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT };
424 			vk::VkShaderEXT nullShaders[] = { VK_NULL_HANDLE, VK_NULL_HANDLE };
425 			vk.cmdSetPrimitiveTopology(*cmdBuffer, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
426 			if (m_params.unbindWithNullpShaders)
427 				vk.cmdBindShadersEXT(*cmdBuffer, 2u, stages, DE_NULL);
428 			else
429 				vk.cmdBindShadersEXT(*cmdBuffer, 2u, stages, nullShaders);
430 		}
431 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
432 	}
433 	else if (m_params.testType == DRAW_DISPATCH_DRAW)
434 	{
435 		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader, taskSupported, meshSupported);
436 		if (m_params.setStateAfter)
437 			setDynamicStates(*cmdBuffer, tessellationSupported);
438 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
439 		vk::VkShaderStageFlagBits computeStage = vk::VK_SHADER_STAGE_COMPUTE_BIT;
440 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &computeStage, &*compShader);
441 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
442 	}
443 	else if (m_params.testType == DISPATCH_DRAW_DISPATCH)
444 	{
445 		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1, &descriptorSet1.get(), 0, DE_NULL);
446 		vk::VkShaderStageFlagBits computeStage = vk::VK_SHADER_STAGE_COMPUTE_BIT;
447 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &computeStage, &*compShader);
448 		vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
449 		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader, taskSupported, meshSupported);
450 		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1, &descriptorSet2.get(), 0, DE_NULL);
451 		vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
452 	}
453 
454 	if (m_params.testType != DISPATCH_DRAW_DISPATCH)
455 		vk::endRendering(vk, *cmdBuffer);
456 
457 	vk::VkImageMemoryBarrier postImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
458 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarrier);
459 
460 	const vk::VkBufferImageCopy	copyRegion = vk::makeBufferImageCopy(extent, subresourceLayers);
461 	vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, &copyRegion);
462 
463 	vk::endCommandBuffer(vk, *cmdBuffer);
464 
465 	vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
466 
467 	tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(vk::mapVkFormat(colorAttachmentFormat), renderArea.extent.width, renderArea.extent.height, 1, (const void*)colorOutputBuffer->getAllocation().getHostPtr());
468 
469 	const deInt32			width			= resultBuffer.getWidth();
470 	const deInt32			height			= resultBuffer.getHeight();
471 	const float				threshold		= 1.0f / 256.0f;
472 	deInt32					xOffset1		= width / 8;
473 	deInt32					yOffset1		= height / 8;
474 	deInt32					xOffset2		= width / 8;
475 	deInt32					yOffset2		= height / 8;
476 	tcu::Vec4				expectedColor1	= tcu::Vec4(0.75f, 0.75f, 0.75f, 0.75f);
477 	tcu::Vec4				expectedColor2	= tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
478 	tcu::Vec4				blackColor		= tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
479 
480 	if (m_params.testType == PASSTHROUGH_GEOM)
481 	{
482 		yOffset1 = height / 4;
483 		xOffset2 = xOffset1;
484 		yOffset2 = yOffset1;
485 	}
486 	else if (m_params.testType == SWAP)
487 	{
488 		if (m_params.stage == vk::VK_SHADER_STAGE_VERTEX_BIT)
489 		{
490 			xOffset2 = 0;
491 			yOffset2 = 0;
492 		}
493 		else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
494 		{
495 			xOffset2 = 10;
496 			yOffset2 = 10;
497 		}
498 		else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
499 		{
500 			xOffset2 = 12;
501 			yOffset2 = height / 8;
502 		}
503 		else if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
504 		{
505 			xOffset2 = width / 8;
506 			yOffset2 = 12;
507 		}
508 		else if (m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
509 		{
510 			expectedColor1 = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
511 		}
512 	}
513 	else if (m_params.testType == DISABLED)
514 	{
515 		if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
516 		{
517 			yOffset1 = height / 4;
518 			xOffset2 = 16;
519 			yOffset2 = 16;
520 		}
521 		else
522 		{
523 			xOffset1 = width / 4;
524 			xOffset2 = 16;
525 			yOffset2 = 16;
526 		}
527 	}
528 	else if (m_params.testType == UNBIND)
529 	{
530 		if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
531 		{
532 			xOffset2 = xOffset1;
533 			yOffset2 = yOffset1 * 2;
534 		}
535 		else
536 		{
537 			xOffset2 = xOffset1 * 2;
538 			yOffset2 = yOffset1;
539 		}
540 	}
541 	else if (m_params.testType == DRAW_DISPATCH_DRAW)
542 	{
543 		xOffset2 = xOffset1;
544 		yOffset2 = yOffset1;
545 	}
546 
547 	if (m_params.testType == DISPATCH_DRAW_DISPATCH)
548 	{
549 		for (deUint32 i = 0; i < 2; ++i)
550 		{
551 			const vk::Allocation& outputBufferAllocation = i == 0 ? outputBuffer1.getAllocation() : outputBuffer2.getAllocation();
552 			invalidateAlloc(vk, device, outputBufferAllocation);
553 
554 			const deUint32* bufferPtr = static_cast<deUint32*>(outputBufferAllocation.getHostPtr());
555 
556 			for (deUint32 j = 0; j < 16; ++j)
557 			{
558 				if (bufferPtr[j] != j)
559 					return tcu::TestStatus::fail("Fail");
560 			}
561 		}
562 		return tcu::TestStatus::pass("Pass");
563 	}
564 
565 	for (deInt32 j = 0; j < height; ++j)
566 	{
567 		for (deInt32 i = 0; i < width; ++i)
568 		{
569 			const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
570 
571 			bool first = i >= xOffset1 && i < width - xOffset1 && j >= yOffset1 && j < height - yOffset1;
572 			bool second = i >= xOffset2 && i < width - xOffset2 && j >= yOffset2 && j < height - yOffset2;
573 			tcu::Vec4 expectedColor = blackColor;
574 			if (first && second)
575 				expectedColor = expectedColor1;
576 			else if (first || second)
577 				expectedColor = expectedColor2;
578 
579 			if (deFloatAbs(color.x() - expectedColor.x()) > threshold || deFloatAbs(color.y() - expectedColor.y()) > threshold || deFloatAbs(color.z() - expectedColor.z()) > threshold || deFloatAbs(color.w() - expectedColor.w()) > threshold)
580 			{
581 				log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be (" << expectedColor << "), but was (" << color << ")" << tcu::TestLog::EndMessage;
582 				return tcu::TestStatus::fail("Fail");
583 			}
584 		}
585 	}
586 
587 	return tcu::TestStatus::pass("Pass");
588 }
589 
590 class ShaderObjectBindingDrawCase : public vkt::TestCase
591 {
592 public:
ShaderObjectBindingDrawCase(tcu::TestContext & testCtx,const std::string & name,const BindingDrawParams & params)593 					ShaderObjectBindingDrawCase		(tcu::TestContext& testCtx, const std::string& name, const BindingDrawParams& params)
594 												: vkt::TestCase		(testCtx, name)
595 												, m_params			(params)
596 												{}
~ShaderObjectBindingDrawCase(void)597 	virtual			~ShaderObjectBindingDrawCase	(void) {}
598 
599 	void			checkSupport				(vkt::Context& context) const override;
600 	virtual void	initPrograms				(vk::SourceCollections& programCollection) const override;
createInstance(Context & context) const601 	TestInstance*	createInstance				(Context& context) const override { return new ShaderObjectBindingDrawInstance(context, m_params); }
602 private:
603 	BindingDrawParams m_params;
604 };
605 
checkSupport(Context & context) const606 void ShaderObjectBindingDrawCase::checkSupport (Context& context) const
607 {
608 	context.requireDeviceFunctionality("VK_EXT_shader_object");
609 
610 	if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ||
611 		m_params.binaryStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_params.binaryStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
612 		context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
613 
614 	if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT || m_params.binaryStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
615 		context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
616 }
617 
initPrograms(vk::SourceCollections & programCollection) const618 void ShaderObjectBindingDrawCase::initPrograms(vk::SourceCollections& programCollection) const
619 {
620 	vk::addBasicShaderObjectShaders(programCollection);
621 
622 	std::stringstream passThroughGeom;
623 	std::stringstream blendFrag;
624 	std::stringstream vertAlt;
625 	std::stringstream geomAlt;
626 	std::stringstream tescAlt;
627 	std::stringstream teseAlt;
628 	std::stringstream fragAlt;
629 	std::stringstream vertNoTess;
630 	std::stringstream vertNoGeom;
631 	std::stringstream vertNoTessGeom;
632 	std::stringstream vertAltNoTess;
633 	std::stringstream vertAltNoGeom;
634 	std::stringstream vertAltNoTessGeom;
635 
636 	vertNoTess
637 		<< "#version 450\n"
638 		<< "void main() {\n"
639 		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
640 		<< "    gl_Position = vec4((pos.x - 0.5f) * 1.5f, pos.y - 0.5f, 0.0f, 1.0f);\n"
641 		<< "}\n";
642 
643 	vertNoGeom
644 		<< "#version 450\n"
645 		<< "void main() {\n"
646 		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
647 		<< "    gl_Position = vec4(pos.x - 0.5f, (pos.y - 0.5f) * 1.5f, 0.0f, 1.0f);\n"
648 		<< "}\n";
649 
650 	vertNoTessGeom
651 		<< "#version 450\n"
652 		<< "void main() {\n"
653 		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
654 		<< "    gl_Position = vec4((pos - 0.5f) * 1.5f, 0.0f, 1.0f);\n"
655 		<< "}\n";
656 
657 	passThroughGeom
658 		<< "#version 450\n"
659 		<< "layout(triangles) in;\n"
660 		<< "layout(triangle_strip, max_vertices = 4) out;\n"
661 		<< "\n"
662 		<< "void main(void)\n"
663 		<< "{\n"
664 		<< "    gl_Position = gl_in[0].gl_Position;\n"
665 		<< "    EmitVertex();\n"
666 		<< "    gl_Position = gl_in[1].gl_Position;\n"
667 		<< "    EmitVertex();\n"
668 		<< "    gl_Position = gl_in[2].gl_Position;\n"
669 		<< "    EmitVertex();\n"
670 		<< "    EndPrimitive();\n"
671 		<< "}\n";
672 
673 	blendFrag
674 		<< "#version 450\n"
675 		<< "layout (location=0) out vec4 outColor;\n"
676 		<< "void main() {\n"
677 		<< "    outColor = vec4(0.5f, 0.5f, 0.5f, 0.5f);\n"
678 		<< "}\n";
679 
680 	vertAlt
681 		<< "#version 450\n";
682 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
683 		vertAlt
684 			<< "layout (location = 0) out vec4 color;\n";
685 	vertAlt
686 		<< "void main() {\n"
687 		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
688 		<< "    gl_Position = vec4((pos - 0.5f) * 2, 0.0f, 1.0f);\n";
689 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
690 		vertAlt
691 			<< "color = vec4(1.0f);\n";
692 	vertAlt
693 		<< "}\n";
694 
695 	vertAltNoTess
696 		<< "#version 450\n";
697 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
698 		vertAltNoTess
699 		<< "layout (location = 0) out vec4 color;\n";
700 	vertAltNoTess
701 		<< "void main() {\n"
702 		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
703 		<< "    gl_Position = vec4((pos.x - 0.5f) * 2.0f * 1.5f, (pos.y - 0.5f) * 2.0f, 0.0f, 1.0f);\n";
704 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
705 		vertAltNoTess
706 		<< "	color = vec4(1.0f);\n";
707 	vertAltNoTess
708 		<< "}\n";
709 
710 	vertAltNoGeom
711 		<< "#version 450\n";
712 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
713 		vertAltNoGeom
714 		<< "layout (location = 0) out vec4 color;\n";
715 	vertAltNoGeom
716 		<< "void main() {\n"
717 		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
718 		<< "    gl_Position = vec4((pos.x - 0.5f) * 2.0f, (pos.y - 0.5f) * 2.0f * 1.5f, 0.0f, 1.0f);\n";
719 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
720 		vertAltNoGeom
721 		<< "	color = vec4(1.0f);\n";
722 	vertAltNoGeom
723 		<< "}\n";
724 
725 	vertAltNoTessGeom
726 		<< "#version 450\n";
727 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
728 		vertAltNoTessGeom
729 		<< "layout (location = 0) out vec4 color;\n";
730 	vertAltNoTessGeom
731 		<< "void main() {\n"
732 		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
733 		<< "    gl_Position = vec4((pos - 0.5f) * 2 * 1.5f, 0.0f, 1.0f);\n";
734 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
735 		vertAltNoTessGeom
736 		<< "	color = vec4(1.0f);\n";
737 	vertAltNoTessGeom
738 		<< "}\n";
739 
740 	tescAlt
741 		<< "#version 450\n"
742 		<< "\n"
743 		<< "layout(vertices = 4) out;\n";
744 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
745 		tescAlt
746 			<< "layout (location = 0) out vec4 color[];\n";
747 	tescAlt
748 		<< "\n"
749 		<< "void main (void)\n"
750 		<< "{\n"
751 		<< "    if (gl_InvocationID == 0) {\n"
752 		<< "		gl_TessLevelInner[0] = 1.0;\n"
753 		<< "		gl_TessLevelInner[1] = 1.0;\n"
754 		<< "		gl_TessLevelOuter[0] = 1.0;\n"
755 		<< "		gl_TessLevelOuter[1] = 1.0;\n"
756 		<< "		gl_TessLevelOuter[2] = 1.0;\n"
757 		<< "		gl_TessLevelOuter[3] = 1.0;\n"
758 		<< "	}\n"
759 		<< "	vec4 pos = gl_in[gl_InvocationID].gl_Position;\n"
760 		<< "	pos.xy *= 0.5f;\n"
761 		<< "    gl_out[gl_InvocationID].gl_Position = pos;\n";
762 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
763 		tescAlt
764 			<< "	color[gl_InvocationID] = vec4(1.0f);\n";
765 	tescAlt
766 		<< "}\n";
767 
768 	teseAlt
769 		<< "#version 450\n"
770 		<< "\n"
771 		<< "layout(quads, equal_spacing) in;\n";
772 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
773 		teseAlt
774 		<< "layout (location = 0) out vec4 color;\n";
775 	teseAlt
776 		<< "\n"
777 		<< "void main (void)\n"
778 		<< "{\n"
779 		<< "	float u = gl_TessCoord.x;\n"
780 		<< "	float v = gl_TessCoord.y;\n"
781 		<< "	float omu = 1.0f - u;\n"
782 		<< "	float omv = 1.0f - v;\n"
783 		<< "	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"
784 		<< "	gl_Position.x *= 0.5f;\n";
785 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
786 		teseAlt
787 		<< "	color = vec4(1.0f);\n";
788 	teseAlt
789 		<< "}\n";
790 
791 	geomAlt
792 		<< "#version 450\n"
793 		<< "layout(triangles) in;\n"
794 		<< "layout(triangle_strip, max_vertices = 4) out;\n";
795 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
796 		geomAlt
797 			<< "layout (location = 0) out vec4 color;\n";
798 	geomAlt
799 		<< "\n"
800 		<< "void main(void)\n"
801 		<< "{\n"
802 		<< "    gl_Position = gl_in[0].gl_Position;\n"
803 		<< "	gl_Position.y *= 0.5f;\n"
804 		<< "    EmitVertex();\n"
805 		<< "    gl_Position = gl_in[1].gl_Position;\n"
806 		<< "	gl_Position.y *= 0.5f;\n"
807 		<< "    EmitVertex();\n"
808 		<< "    gl_Position = gl_in[2].gl_Position;\n"
809 		<< "	gl_Position.y *= 0.5f;\n"
810 		<< "    EmitVertex();\n"
811 		<< "    EndPrimitive();\n";
812 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
813 		geomAlt
814 			<< "	color = vec4(1.0f);\n";
815 	geomAlt
816 		<< "}\n";
817 
818 	fragAlt
819 		<< "#version 450\n"
820 		<< "layout (location=0) out vec4 outColor;\n";
821 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
822 		fragAlt
823 			<< "layout (location = 1) out vec4 color;\n";
824 	fragAlt
825 		<< "void main() {\n"
826 		<< "    outColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n";
827 	if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
828 		fragAlt
829 			<< "color = vec4(1.0f);\n";
830 	fragAlt
831 		<< "}\n";
832 
833 	programCollection.glslSources.add("passThroughGeom") << glu::GeometrySource(passThroughGeom.str());
834 	programCollection.glslSources.add("blendFrag") << glu::FragmentSource(blendFrag.str());
835 	programCollection.glslSources.add("vertAlt") << glu::VertexSource(vertAlt.str());
836 	programCollection.glslSources.add("tescAlt") << glu::TessellationControlSource(tescAlt.str());
837 	programCollection.glslSources.add("teseAlt") << glu::TessellationEvaluationSource(teseAlt.str());
838 	programCollection.glslSources.add("geomAlt") << glu::GeometrySource(geomAlt.str());
839 	programCollection.glslSources.add("fragAlt") << glu::FragmentSource(fragAlt.str());
840 
841 	programCollection.glslSources.add("vertNoTess") << glu::VertexSource(vertNoTess.str());
842 	programCollection.glslSources.add("vertNoGeom") << glu::VertexSource(vertNoGeom.str());
843 	programCollection.glslSources.add("vertNoTessGeom") << glu::VertexSource(vertNoTessGeom.str());
844 	programCollection.glslSources.add("vertAltNoTess") << glu::VertexSource(vertAltNoTess.str());
845 	programCollection.glslSources.add("vertAltNoGeom") << glu::VertexSource(vertAltNoGeom.str());
846 	programCollection.glslSources.add("vertAltNoTessGeom") << glu::VertexSource(vertAltNoTessGeom.str());
847 }
848 
849 
850 class ShaderObjectBindingInstance : public vkt::TestInstance
851 {
852 public:
ShaderObjectBindingInstance(Context & context,const BindingParams & params)853 								ShaderObjectBindingInstance		(Context& context, const BindingParams& params)
854 																: vkt::TestInstance	(context)
855 																, m_params			(params)
856 																{}
~ShaderObjectBindingInstance(void)857 	virtual						~ShaderObjectBindingInstance	(void) {}
858 
859 	tcu::TestStatus				iterate							(void) override;
860 private:
861 	BindingParams m_params;
862 };
863 
iterate(void)864 tcu::TestStatus ShaderObjectBindingInstance::iterate (void)
865 {
866 	const vk::VkInstance				instance					= m_context.getInstance();
867 	const vk::InstanceDriver			instanceDriver				(m_context.getPlatformInterface(), instance);
868 	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
869 	const vk::VkDevice					device						= m_context.getDevice();
870 	const vk::VkQueue					queue						= m_context.getUniversalQueue();
871 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
872 
873 	const auto							meshShaderFeatures			= m_context.getMeshShaderFeatures();
874 	const bool							tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
875 	const bool							geometrySupported			= m_context.getDeviceFeatures().geometryShader;
876 	const auto&							binaries					= m_context.getBinaryCollection();
877 
878     const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
879         vk::DescriptorSetLayoutBuilder()
880         .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT | ((m_params.useMeshShaders && meshShaderFeatures.meshShader) ? vk::VkShaderStageFlags{ vk::VK_SHADER_STAGE_MESH_BIT_EXT } : vk::VkShaderStageFlags{ 0 }))
881         .build(vk, device));
882 
883 	vk::Move<vk::VkShaderEXT>			vertShader					= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, binaries.get("vert"), tessellationSupported, geometrySupported));
884 	vk::Move<vk::VkShaderEXT>			tescShader;
885 	vk::Move<vk::VkShaderEXT>			teseShader;
886 	vk::Move<vk::VkShaderEXT>			geomShader;
887 	vk::Move<vk::VkShaderEXT>			fragShader					= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("frag"), tessellationSupported, geometrySupported));
888 	vk::Move<vk::VkShaderEXT>			compShader					= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_COMPUTE_BIT, binaries.get("comp"), tessellationSupported, geometrySupported, &*descriptorSetLayout));
889 	vk::Move<vk::VkShaderEXT>			taskShader;
890 	vk::Move<vk::VkShaderEXT>			meshShader;
891 	if (m_context.getDeviceFeatures().tessellationShader)
892 	{
893 		tescShader = vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, binaries.get("tesc"), tessellationSupported, geometrySupported));
894 		teseShader = vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, binaries.get("tese"), tessellationSupported, geometrySupported));
895 	}
896 	if (m_context.getDeviceFeatures().geometryShader)
897 	{
898 		geomShader = vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, binaries.get("geom"), tessellationSupported, geometrySupported));
899 	}
900 	if (m_params.useMeshShaders)
901 	{
902 		if (meshShaderFeatures.taskShader)
903 			taskShader = vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, binaries.get("task"), tessellationSupported, geometrySupported));
904 		if (meshShaderFeatures.meshShader)
905 			meshShader = vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT, binaries.get("mesh"), tessellationSupported, geometrySupported, &*descriptorSetLayout));
906 	}
907 
908 	const vk::Move<vk::VkCommandPool>	cmdPool		(vk::createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
909 	const vk::Move<vk::VkCommandBuffer>	cmdBuffer	(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
910 
911 	const bool bind[] = { true, false };
912 	for (const auto bindVert : bind)
913 	{
914 		for (const auto bindTesc : bind)
915 		{
916 			for (const auto bindTese : bind)
917 			{
918 				for (const auto bindGeom : bind)
919 				{
920 					for (const auto bindFrag : bind)
921 					{
922 						for (const auto bindComp : bind)
923 						{
924 							for (const auto bindTask : bind)
925 							{
926 								if (bindVert && bindTask)
927 									continue;
928 								for (const auto bindMesh : bind)
929 								{
930 									if (bindVert && bindMesh)
931 										continue;
932 									std::vector<vk::VkShaderStageFlagBits> stages = {
933 										vk::VK_SHADER_STAGE_VERTEX_BIT,
934 										vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
935 										vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
936 										vk::VK_SHADER_STAGE_GEOMETRY_BIT,
937 										vk::VK_SHADER_STAGE_FRAGMENT_BIT,
938 										vk::VK_SHADER_STAGE_COMPUTE_BIT,
939 										vk::VK_SHADER_STAGE_MESH_BIT_EXT,
940 										vk::VK_SHADER_STAGE_TASK_BIT_EXT,
941 									};
942 									std::vector<vk::VkShaderEXT> shaders =
943 									{
944 										bindVert ? *vertShader : VK_NULL_HANDLE,
945 										(bindTesc && m_context.getDeviceFeatures().tessellationShader) ? *tescShader : VK_NULL_HANDLE,
946 										(bindTese && m_context.getDeviceFeatures().tessellationShader) ? *teseShader : VK_NULL_HANDLE,
947 										(bindGeom && m_context.getDeviceFeatures().geometryShader) ? *geomShader : VK_NULL_HANDLE,
948 										bindFrag ? *fragShader : VK_NULL_HANDLE,
949 										bindComp ? *compShader : VK_NULL_HANDLE,
950 										bindMesh ? *meshShader : VK_NULL_HANDLE,
951 										bindTask ? *taskShader : VK_NULL_HANDLE,
952 									};
953 									deUint32 count = 6u;
954 									if (meshShaderFeatures.meshShader)
955 										++count;
956 									if (meshShaderFeatures.taskShader)
957 										++count;
958 									vk::beginCommandBuffer(vk, *cmdBuffer);
959 									vk.cmdBindShadersEXT(*cmdBuffer, count, stages.data(), shaders.data());
960 									vk::endCommandBuffer(vk, *cmdBuffer);
961 									vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
962 								}
963 							}
964 						}
965 					}
966 				}
967 			}
968 		}
969 	}
970 
971 	if (m_context.getDeviceFeatures().tessellationShader && m_context.getDeviceFeatures().geometryShader && meshShaderFeatures.taskShader && meshShaderFeatures.meshShader)
972 	{
973 		std::vector<vk::VkShaderStageFlagBits> stages = {
974 			vk::VK_SHADER_STAGE_VERTEX_BIT,
975 			vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
976 			vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
977 			vk::VK_SHADER_STAGE_GEOMETRY_BIT,
978 			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
979 			vk::VK_SHADER_STAGE_COMPUTE_BIT,
980 			vk::VK_SHADER_STAGE_MESH_BIT_EXT,
981 			vk::VK_SHADER_STAGE_TASK_BIT_EXT,
982 		};
983 		vk::beginCommandBuffer(vk, *cmdBuffer);
984 		vk.cmdBindShadersEXT(*cmdBuffer, (deUint32)stages.size(), stages.data(), DE_NULL);
985 		vk::endCommandBuffer(vk, *cmdBuffer);
986 		vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
987 	}
988 
989 	return tcu::TestStatus::pass("pass");
990 }
991 
992 class MeshShaderObjectBindingInstance : public vkt::TestInstance
993 {
994 public:
MeshShaderObjectBindingInstance(Context & context,const MeshBindingDrawParams & params)995 							MeshShaderObjectBindingInstance		(Context& context, const MeshBindingDrawParams& params)
996 																: vkt::TestInstance	(context)
997 																, m_params			(params)
998 																{}
~MeshShaderObjectBindingInstance(void)999 	virtual					~MeshShaderObjectBindingInstance	(void) {}
1000 
1001 	tcu::TestStatus			iterate								(void) override;
1002 private:
1003 	MeshBindingDrawParams m_params;
1004 };
1005 
iterate(void)1006 tcu::TestStatus MeshShaderObjectBindingInstance::iterate (void)
1007 {
1008 	const vk::VkInstance				instance					= m_context.getInstance();
1009 	const vk::InstanceDriver			instanceDriver				(m_context.getPlatformInterface(), instance);
1010 	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
1011 	const vk::VkDevice					device						= m_context.getDevice();
1012 	const vk::VkQueue					queue						= m_context.getUniversalQueue();
1013 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1014 	auto&								alloc						= m_context.getDefaultAllocator();
1015 	tcu::TestLog&						log							= m_context.getTestContext().getLog();
1016 	const auto							deviceExtensions			= vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
1017 
1018 	vk::VkFormat						colorAttachmentFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
1019 	const auto							subresourceRange			= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1020 
1021 	const vk::VkImageCreateInfo	createInfo =
1022 	{
1023 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
1024 		DE_NULL,									// const void*				pNext
1025 		0u,											// VkImageCreateFlags		flags
1026 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
1027 		colorAttachmentFormat,						// VkFormat					format
1028 		{ 32, 32, 1 },								// VkExtent3D				extent
1029 		1u,											// uint32_t					mipLevels
1030 		1u,											// uint32_t					arrayLayers
1031 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
1032 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
1033 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
1034 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
1035 		0,											// uint32_t					queueFamilyIndexCount
1036 		DE_NULL,									// const uint32_t*			pQueueFamilyIndices
1037 		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
1038 	};
1039 
1040 	de::MovePtr<vk::ImageWithMemory>		image			= de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
1041 	const auto								imageView		= vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
1042 	const vk::VkRect2D						renderArea		= vk::makeRect2D(0, 0, 32, 32);
1043 
1044 	const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
1045 		vk::DescriptorSetLayoutBuilder()
1046 		.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_TASK_BIT_EXT | vk::VK_SHADER_STAGE_MESH_BIT_EXT)
1047 		.build(vk, device));
1048 
1049 	const vk::Unique<vk::VkDescriptorPool>	descriptorPool(
1050 		vk::DescriptorPoolBuilder()
1051 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1052 		.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1053 
1054 	const vk::VkDeviceSize					bufferSizeBytes = sizeof(deUint32) * 4;
1055 	const vk::Unique<vk::VkDescriptorSet>	descriptorSet	(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1056 	const vk::BufferWithMemory				outputBuffer	(vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
1057 
1058 	const vk::VkDescriptorBufferInfo		descriptorInfo	= vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
1059 	vk::DescriptorSetUpdateBuilder()
1060 		.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1061 		.update(vk, device);
1062 
1063 	const auto								pipelineLayout	= makePipelineLayout(vk, device, *descriptorSetLayout);
1064 
1065 	const auto&								binaries		= m_context.getBinaryCollection();
1066 	const auto								taskShader1		= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, binaries.get("task1"), false, false, &*descriptorSetLayout));
1067 	const auto								taskShader2		= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, binaries.get("task2"), false, false, &*descriptorSetLayout));
1068 	const auto								meshShader1		= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT, binaries.get("mesh1"), false, false, &*descriptorSetLayout));
1069 	const auto								meshShader2		= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT, binaries.get("mesh2"), false, false, &*descriptorSetLayout));
1070 	const auto								fragShader		= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("frag"), false, false, &*descriptorSetLayout));
1071 
1072 	const vk::Move<vk::VkCommandPool>		cmdPool			(vk::createCommandPool(vk, device, 0u, queueFamilyIndex));
1073 	const vk::Move<vk::VkCommandBuffer>		cmdBuffer		(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1074 
1075 	const vk::VkClearValue					clearValue		= vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
1076 
1077 	vk::beginCommandBuffer(vk, *cmdBuffer);
1078 
1079 	vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
1080 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &preImageBarrier);
1081 
1082 	vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
1083 	vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, true);
1084 	vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0, 1, &descriptorSet.get(), 0, DE_NULL);
1085 
1086 	std::vector<vk::VkShaderStageFlagBits> nullStages = {
1087 		vk::VK_SHADER_STAGE_VERTEX_BIT,
1088 	};
1089 	if (m_context.getDeviceFeatures().tessellationShader) {
1090 		nullStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
1091 		nullStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
1092 	}
1093 	if (m_context.getDeviceFeatures().geometryShader) {
1094 		nullStages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
1095 	}
1096 	for (const auto& stage : nullStages) {
1097 		vk::VkShaderEXT shader = VK_NULL_HANDLE;
1098 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stage, &shader);
1099 	}
1100 
1101 	const vk::VkShaderStageFlagBits stages[] = {
1102 			vk::VK_SHADER_STAGE_TASK_BIT_EXT,
1103 			vk::VK_SHADER_STAGE_MESH_BIT_EXT,
1104 			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1105 	};
1106 	vk::VkShaderEXT shaders[] = {
1107 		*taskShader1,
1108 		*meshShader1,
1109 		*fragShader,
1110 	};
1111 	vk.cmdBindShadersEXT(*cmdBuffer, 3u, stages, shaders);
1112 	vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1, 1, 1);
1113 	vk::endRendering(vk, *cmdBuffer);
1114 
1115 	vk::VkBufferMemoryBarrier shaderBufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_SHADER_WRITE_BIT, *outputBuffer, 0u, bufferSizeBytes);
1116 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, &shaderBufferBarrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
1117 
1118 	vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_LOAD);
1119 	if (m_params.stage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
1120 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stages[0], &*taskShader2);
1121 	else if (m_params.stage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
1122 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stages[1], &*meshShader2);
1123 	vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1, 1, 1);
1124 
1125 	vk::endRendering(vk, *cmdBuffer);
1126 
1127 	vk::VkImageMemoryBarrier postImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
1128 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarrier);
1129 	vk::VkBufferMemoryBarrier bufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0u, bufferSizeBytes);
1130 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, &bufferBarrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
1131 	vk::endCommandBuffer(vk, *cmdBuffer);
1132 
1133 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1134 
1135 	const vk::Allocation& outputBufferAllocation = outputBuffer.getAllocation();
1136 	invalidateAlloc(vk, device, outputBufferAllocation);
1137 
1138 	const deUint32* bufferPtr = static_cast<deUint32*>(outputBufferAllocation.getHostPtr());
1139 
1140 	if (m_params.stage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
1141 	{
1142 		if (bufferPtr[0] != 4u || bufferPtr[1] != 5u || bufferPtr[2] != 2u || bufferPtr[3] != 3u)
1143 		{
1144 			log << tcu::TestLog::Message << "Buffer values were expected to be [4, 5, 2, 3], but were[" << bufferPtr[0] << ", " << bufferPtr[1] << ", " << bufferPtr[2] << ", " << bufferPtr[3] << ", " << "]" << tcu::TestLog::EndMessage;
1145 			return tcu::TestStatus::fail("Fail");
1146 		}
1147 	}
1148 	else if (m_params.stage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
1149 	{
1150 		if (bufferPtr[0] != 0u || bufferPtr[1] != 1u || bufferPtr[2] != 6u || bufferPtr[3] != 7u)
1151 		{
1152 			log << tcu::TestLog::Message << "Buffer values were expected to be [0, 1, 6, 7], but were[" << bufferPtr[0] << ", " << bufferPtr[1] << ", " << bufferPtr[2] << ", " << bufferPtr[3] << ", " << "]" << tcu::TestLog::EndMessage;
1153 			return tcu::TestStatus::fail("Fail");
1154 		}
1155 	}
1156 
1157 	return tcu::TestStatus::pass("pass");
1158 }
1159 
1160 class MeshShaderObjectBindingCase : public vkt::TestCase
1161 {
1162 public:
MeshShaderObjectBindingCase(tcu::TestContext & testCtx,const std::string & name,const MeshBindingDrawParams & params)1163 					MeshShaderObjectBindingCase		(tcu::TestContext& testCtx, const std::string& name, const MeshBindingDrawParams& params)
1164 													: vkt::TestCase		(testCtx, name)
1165 													, m_params			(params)
1166 													{}
~MeshShaderObjectBindingCase(void)1167 	virtual			~MeshShaderObjectBindingCase	(void) {}
1168 
1169 	void			checkSupport					(vkt::Context& context) const override;
1170 	virtual void	initPrograms					(vk::SourceCollections& programCollection) const override;
createInstance(Context & context) const1171 	TestInstance*	createInstance					(Context& context) const override { return new MeshShaderObjectBindingInstance(context, m_params); }
1172 private:
1173 	MeshBindingDrawParams m_params;
1174 };
1175 
checkSupport(vkt::Context & context) const1176 void MeshShaderObjectBindingCase::checkSupport (vkt::Context& context) const
1177 {
1178 	context.requireDeviceFunctionality("VK_EXT_shader_object");
1179 	context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1180 	const auto& features = context.getMeshShaderFeaturesEXT();
1181 	if (!features.taskShader)
1182 		TCU_THROW(NotSupportedError, "Task shaders not supported");
1183 	if (!features.meshShader)
1184 		TCU_THROW(NotSupportedError, "Mesh shaders not supported");
1185 }
1186 
initPrograms(vk::SourceCollections & programCollection) const1187 void MeshShaderObjectBindingCase::initPrograms (vk::SourceCollections& programCollection) const
1188 {
1189 	std::stringstream task1;
1190 	std::stringstream task2;
1191 	std::stringstream mesh1;
1192 	std::stringstream mesh2;
1193 	std::stringstream frag;
1194 
1195 	task1
1196 		<< "#version 450\n"
1197 		<< "#extension GL_EXT_mesh_shader : enable\n"
1198 		<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1199 		<< "layout(set = 0, binding = 0) buffer Output {\n"
1200 		<< "    uint values[4];\n"
1201 		<< "} buffer_out;\n\n"
1202 		<< "void main ()\n"
1203 		<< "{\n"
1204 		<< "    buffer_out.values[0] = 0u;\n"
1205 		<< "    buffer_out.values[1] = 1u;\n"
1206 		<< "    EmitMeshTasksEXT(1u, 1u, 1u);\n"
1207 		<< "}\n";
1208 
1209 	task2
1210 		<< "#version 450\n"
1211 		<< "#extension GL_EXT_mesh_shader : enable\n"
1212 		<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1213 		<< "layout(set = 0, binding = 0) buffer Output {\n"
1214 		<< "    uint values[4];\n"
1215 		<< "} buffer_out;\n\n"
1216 		<< "void main ()\n"
1217 		<< "{\n"
1218 		<< "    buffer_out.values[0] = 4u;\n"
1219 		<< "    buffer_out.values[1] = 5u;\n"
1220 		<< "    EmitMeshTasksEXT(1u, 1u, 1u);\n"
1221 		<< "}\n";
1222 
1223 	mesh1
1224 		<< "#version 460\n"
1225 		<< "#extension GL_EXT_mesh_shader : require\n"
1226 		<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1227 		<< "layout(max_vertices = 3) out;\n"
1228 		<< "layout(max_primitives = 1) out;\n"
1229 		<< "layout(triangles) out;\n"
1230 		<< "layout(set = 0, binding = 0) buffer Output {\n"
1231 		<< "    uint values[4];\n"
1232 		<< "} buffer_out;\n\n"
1233 		<< "void main() {\n"
1234 		<< "      SetMeshOutputsEXT(3, 1);\n"
1235 		<< "      gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1236 		<< "      gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1237 		<< "      gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0f, 1.0f);\n"
1238 		<< "      gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1239 		<< "      buffer_out.values[2] = 2u;\n"
1240 		<< "      buffer_out.values[3] = 3u;\n"
1241 		<< "}\n";
1242 
1243 	mesh2
1244 		<< "#version 460\n"
1245 		<< "#extension GL_EXT_mesh_shader : require\n"
1246 		<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1247 		<< "layout(max_vertices = 3) out;\n"
1248 		<< "layout(max_primitives = 1) out;\n"
1249 		<< "layout(triangles) out;\n"
1250 		<< "layout(set = 0, binding = 0) buffer Output {\n"
1251 		<< "    uint values[4];\n"
1252 		<< "} buffer_out;\n\n"
1253 		<< "void main() {\n"
1254 		<< "      SetMeshOutputsEXT(3, 1);\n"
1255 		<< "      gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1256 		<< "      gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1257 		<< "      gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0f, 1.0f);\n"
1258 		<< "      gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1259 		<< "      buffer_out.values[2] = 6u;\n"
1260 		<< "      buffer_out.values[3] = 7u;\n"
1261 		<< "}\n";
1262 
1263 	frag
1264 		<< "#version 450\n"
1265 		<< "layout (location=0) out vec4 outColor;\n"
1266 		<< "void main() {\n"
1267 		<< "    outColor = vec4(1.0f);\n"
1268 		<< "}\n";
1269 
1270 	programCollection.glslSources.add("task1") << glu::TaskSource(task1.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1271 	programCollection.glslSources.add("task2") << glu::TaskSource(task2.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1272 	programCollection.glslSources.add("mesh1") << glu::MeshSource(mesh1.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1273 	programCollection.glslSources.add("mesh2") << glu::MeshSource(mesh2.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1274 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1275 }
1276 
1277 class ShaderObjectBindingCase : public vkt::TestCase
1278 {
1279 public:
ShaderObjectBindingCase(tcu::TestContext & testCtx,const std::string & name,const BindingParams & params)1280 					ShaderObjectBindingCase		(tcu::TestContext& testCtx, const std::string& name, const BindingParams& params)
1281 												: vkt::TestCase		(testCtx, name)
1282 												, m_params			(params)
1283 												{}
~ShaderObjectBindingCase(void)1284 	virtual			~ShaderObjectBindingCase	(void) {}
1285 
1286 	void			checkSupport				(vkt::Context& context) const override;
1287 	virtual void	initPrograms				(vk::SourceCollections& programCollection) const override;
createInstance(Context & context) const1288 	TestInstance*	createInstance				(Context& context) const override { return new ShaderObjectBindingInstance(context, m_params); }
1289 private:
1290 	BindingParams m_params;
1291 };
1292 
checkSupport(Context & context) const1293 void ShaderObjectBindingCase::checkSupport (Context& context) const
1294 {
1295 	context.requireDeviceFunctionality("VK_EXT_shader_object");
1296 	if (m_params.useMeshShaders)
1297 		context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1298 }
1299 
initPrograms(vk::SourceCollections & programCollection) const1300 void ShaderObjectBindingCase::initPrograms (vk::SourceCollections& programCollection) const
1301 {
1302 	vk::addBasicShaderObjectShaders(programCollection);
1303 
1304 	if (m_params.useMeshShaders)
1305 	{
1306 		std::stringstream task;
1307 		std::stringstream mesh;
1308 
1309 		task
1310 			<< "#version 450\n"
1311 			<< "#extension GL_EXT_mesh_shader : enable\n"
1312 			<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1313 			<< "void main ()\n"
1314 			<< "{\n"
1315 			<< "	EmitMeshTasksEXT(1u, 1u, 1u);\n"
1316 			<< "}\n";
1317 
1318 		mesh
1319 			<< "#version 460\n"
1320 			<< "#extension GL_EXT_mesh_shader : require\n"
1321 			<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1322 			<< "layout(max_vertices = 3) out;\n"
1323 			<< "layout(max_primitives = 1) out;\n"
1324 			<< "layout(triangles) out;\n"
1325 			<< "layout(set = 0, binding = 0) buffer Output {\n"
1326 			<< "    uint values[4];\n"
1327 			<< "} buffer_out;\n\n"
1328 			<< "void main() {\n"
1329 			<< "      SetMeshOutputsEXT(3, 1);\n"
1330 			<< "      gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1331 			<< "      gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1332 			<< "      gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0f, 1.0f);\n"
1333 			<< "      gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1334 			<< "      buffer_out.values[0] = 0u;\n"
1335 			<< "      buffer_out.values[1] = 1u;\n"
1336 			<< "      buffer_out.values[2] = 2u;\n"
1337 			<< "      buffer_out.values[3] = 3u;\n"
1338 			<< "}\n";
1339 
1340 		programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1341 		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1342 	}
1343 }
1344 
1345 }
1346 
1347 
createShaderObjectBindingTests(tcu::TestContext & testCtx)1348 tcu::TestCaseGroup* createShaderObjectBindingTests (tcu::TestContext& testCtx)
1349 {
1350 	de::MovePtr<tcu::TestCaseGroup> bindingGroup(new tcu::TestCaseGroup(testCtx, "binding"));
1351 
1352 	BindingDrawParams params;
1353 	params.testType = PASSTHROUGH_GEOM;
1354 	params.stage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1355 	params.unusedOutputs = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
1356 	params.binaryStage = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
1357 	params.bindUnsupported = false;
1358 	params.setStateAfter = false;
1359 	params.unbindWithNullpShaders = false;
1360 
1361 	bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "unbind_passthrough_geom", params));
1362 
1363 	const struct
1364 	{
1365 		vk::VkShaderStageFlagBits stage;
1366 		const char* name;
1367 	} stageTest[] =
1368 	{
1369 		{ vk::VK_SHADER_STAGE_VERTEX_BIT,					"vert" },
1370 		{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		"tesc" },
1371 		{ vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,	"tese" },
1372 		{ vk::VK_SHADER_STAGE_GEOMETRY_BIT,					"geom" },
1373 		{ vk::VK_SHADER_STAGE_FRAGMENT_BIT,					"frag" },
1374 	};
1375 	params.testType = SWAP;
1376 	for (const auto& stage : stageTest)
1377 	{
1378 		params.stage = stage.stage;
1379 		params.unusedOutputs = vk::VK_SHADER_STAGE_ALL; // Unused
1380 		params.binaryStage = vk::VK_SHADER_STAGE_ALL; // Unused
1381 		params.setStateAfter = false;
1382 		std::string name = "swap_" + std::string(stage.name);
1383 		bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, name.c_str(), params));
1384 		for (const auto& unusedOutputs : stageTest)
1385 		{
1386 			for (const auto& binaryStage : stageTest)
1387 			{
1388 				for (deUint32 i = 0; i < 2; ++i)
1389 				{
1390 					params.stage = stage.stage;
1391 					params.unusedOutputs = unusedOutputs.stage;
1392 					params.binaryStage = binaryStage.stage;
1393 					params.setStateAfter = (bool)i;
1394 					std::string name2 = "swap_" + std::string(stage.name) + "_unused_output_" + std::string(unusedOutputs.name) + "_binary_" + std::string(binaryStage.name) + "_" + ((i == 0) ? "before" : "after");
1395 					bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, name2.c_str(), params));
1396 				}
1397 			}
1398 		}
1399 	}
1400 
1401 	params.unusedOutputs = vk::VK_SHADER_STAGE_ALL;
1402 	params.binaryStage = vk::VK_SHADER_STAGE_ALL;
1403 
1404 	const struct
1405 	{
1406 		vk::VkShaderStageFlagBits stage;
1407 		const char* name;
1408 	} unbindStageTest[] =
1409 	{
1410 		{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		"tesc" },
1411 		{ vk::VK_SHADER_STAGE_GEOMETRY_BIT,					"geom" },
1412 	};
1413 	params.testType = UNBIND;
1414 	params.setStateAfter = false;
1415 	for (const auto& stage : unbindStageTest)
1416 	{
1417 		for (deUint32 i = 0; i < 2; ++i)
1418 		{
1419 			params.stage = stage.stage;
1420 			params.unbindWithNullpShaders = (bool)i;
1421 			std::string name = "unbind_" + std::string(stage.name) + (params.unbindWithNullpShaders ? "_null_pshaders" : "_null_handle");
1422 			bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, name.c_str(), params));
1423 		}
1424 	}
1425 
1426 	const struct
1427 	{
1428 		vk::VkShaderStageFlagBits stage;
1429 		const char* name;
1430 	} meshStageTest[] =
1431 	{
1432 		{ vk::VK_SHADER_STAGE_TASK_BIT_EXT,		"task" },
1433 		{ vk::VK_SHADER_STAGE_MESH_BIT_EXT,		"mesh" },
1434 	};
1435 
1436 	for (const auto& stage : meshStageTest)
1437 	{
1438 		MeshBindingDrawParams meshParams;
1439 		meshParams.stage = stage.stage;
1440 		std::string name = "mesh_swap_" + std::string(stage.name);
1441 		bindingGroup->addChild(new MeshShaderObjectBindingCase(testCtx, name.c_str(), meshParams));
1442 	}
1443 
1444 	params.testType = DISABLED;
1445 	params.stage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1446 	bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_geom", params));
1447 	params.stage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1448 	bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_tess", params));
1449 	params.stage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1450 	params.bindUnsupported = true;
1451 	bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_geom_bind", params));
1452 	params.stage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1453 	bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_tess_bind", params));
1454 	params.testType = DRAW_DISPATCH_DRAW;
1455 	bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "draw_dispatch_draw", params));
1456 	params.testType = DISPATCH_DRAW_DISPATCH;
1457 	bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "dispatch_draw_dispatch", params));
1458 
1459 	BindingParams bindingParams;
1460 	bindingParams.useMeshShaders = false;
1461 	bindingGroup->addChild(new ShaderObjectBindingCase(testCtx, "bindings", bindingParams));
1462 	bindingParams.useMeshShaders = true;
1463 	bindingGroup->addChild(new ShaderObjectBindingCase(testCtx, "bindings_mesh_shaders", bindingParams));
1464 
1465 	return bindingGroup.release();
1466 }
1467 
1468 } // ShaderObject
1469 } // vkt
1470