• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 Google Inc.
7  * Copyright (c) 2018 ARM Limited.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Dynamic Offset Tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktPipelineDynamicOffsetTests.hpp"
27 #include "vktPipelineClearUtil.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktPipelineReferenceRenderer.hpp"
31 #include "vktTestCase.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRef.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "vkDeviceUtil.hpp"
42 #include "vkBuilderUtil.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "deMemory.h"
45 #include "deUniquePtr.hpp"
46 #include "tcuTestLog.hpp"
47 #include <array>
48 #include <cmath>
49 #include <vector>
50 #include <sstream>
51 
52 namespace vkt
53 {
54 namespace pipeline
55 {
56 
57 using namespace vk;
58 using namespace std;
59 using de::UniquePtr;
60 
61 namespace
62 {
63 typedef de::SharedPtr<Unique<VkBuffer> >		VkBufferSp;
64 typedef de::SharedPtr<Allocation>				AllocationSp;
65 typedef de::SharedPtr<Unique<VkCommandBuffer> >	VkCommandBufferSp;
66 typedef de::SharedPtr<Unique<VkRenderPass> >	VkRenderPassSp;
67 typedef de::SharedPtr<Unique<VkFramebuffer> >	VkFramebufferSp;
68 
69 enum class GroupingStrategy
70 {
71 	SINGLE_SET	= 0,
72 	MULTISET	= 1,
73 	ARRAYS		= 2,
74 };
75 
76 struct TestParams
77 {
78 	PipelineConstructionType	pipelineConstructionType;
79 	VkDescriptorType			descriptorType;
80 	deUint32					numCmdBuffers;
81 	bool						reverseOrder;
82 	deUint32					numDescriptorSetBindings;
83 	deUint32					numDynamicBindings;
84 	deUint32					numNonDynamicBindings;
85 	GroupingStrategy			groupingStrategy;
86 };
87 #ifndef CTS_USES_VULKANSC
createQuads(deUint32 numQuads,float size)88 vector<Vertex4RGBA> createQuads (deUint32 numQuads, float size)
89 {
90 	vector<Vertex4RGBA>	vertices;
91 
92 	for (deUint32 quadNdx = 0; quadNdx < numQuads; quadNdx++)
93 	{
94 		const float			xOffset				= -0.5f + (float)quadNdx;
95 		const tcu::Vec4		color				(0.0f);
96 		const Vertex4RGBA	lowerLeftVertex		= {tcu::Vec4(-size + xOffset, -size, 0.0f, 1.0f), color};
97 		const Vertex4RGBA	lowerRightVertex	= {tcu::Vec4(size + xOffset, -size, 0.0f, 1.0f), color};
98 		const Vertex4RGBA	UpperLeftVertex		= {tcu::Vec4(-size + xOffset, size, 0.0f, 1.0f), color};
99 		const Vertex4RGBA	UpperRightVertex	= {tcu::Vec4(size + xOffset, size, 0.0f, 1.0f), color};
100 
101 		vertices.push_back(lowerLeftVertex);
102 		vertices.push_back(lowerRightVertex);
103 		vertices.push_back(UpperLeftVertex);
104 		vertices.push_back(UpperLeftVertex);
105 		vertices.push_back(lowerRightVertex);
106 		vertices.push_back(UpperRightVertex);
107 	}
108 
109 	return vertices;
110 }
111 #endif // CTS_USES_VULKANSC
112 
113 static const tcu::Vec4			testColors[]	=
114 {
115 	tcu::Vec4(0.3f, 0.0f, 0.0f, 1.0f),
116 	tcu::Vec4(0.0f, 0.3f, 0.0f, 1.0f),
117 	tcu::Vec4(0.0f, 0.0f, 0.3f, 1.0f),
118 	tcu::Vec4(0.3f, 0.3f, 0.0f, 1.0f),
119 	tcu::Vec4(0.0f, 0.3f, 0.3f, 1.0f),
120 	tcu::Vec4(0.3f, 0.0f, 0.3f, 1.0f)
121 };
122 static constexpr VkDeviceSize	kColorSize		= static_cast<VkDeviceSize>(sizeof(testColors[0]));
123 static constexpr deUint32		kNumTestColors	= static_cast<deUint32>(DE_LENGTH_OF_ARRAY(testColors));
124 
compareVectors(const tcu::Vec4 firstVector,const tcu::Vec4 secondVector,const float tolerance)125 bool compareVectors (const tcu::Vec4 firstVector, const tcu::Vec4 secondVector, const float tolerance)
126 {
127 	for (auto i = 0; i < firstVector.SIZE; i++)
128 	{
129 		if (abs(firstVector[i] - secondVector[i]) > tolerance)
130 			return false;
131 	}
132 
133 	return true;
134 }
135 
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)136 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
137 {
138 	const VkImageCreateInfo imageParams =
139 	{
140 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
141 		DE_NULL,								// const void*				pNext;
142 		(VkImageCreateFlags)0,					// VkImageCreateFlags		flags;
143 		VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
144 		format,									// VkFormat					format;
145 		makeExtent3D(size.x(), size.y(), 1),	// VkExtent3D				extent;
146 		1u,										// deUint32					mipLevels;
147 		1u,										// deUint32					arrayLayers;
148 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
149 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
150 		usage,									// VkImageUsageFlags		usage;
151 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
152 		0u,										// deUint32					queueFamilyIndexCount;
153 		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
154 		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
155 	};
156 
157 	return imageParams;
158 }
159 
160 class DynamicOffsetTestInstance : public vkt::TestInstance
161 {
162 public:
DynamicOffsetTestInstance(Context & context,const TestParams & params)163 	DynamicOffsetTestInstance (Context& context, const TestParams& params)
164 		: vkt::TestInstance	(context)
165 		, m_params			(params)
166 		, m_memAlloc		(context.getDeviceInterface(), context.getDevice(), getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
167 		{}
168 
169 protected:
170 	const TestParams	m_params;
171 	SimpleAllocator		m_memAlloc;
172 };
173 
174 class DynamicOffsetGraphicsTestInstance : public DynamicOffsetTestInstance
175 {
176 public:
177 								DynamicOffsetGraphicsTestInstance	(Context& context, const TestParams& params);
178 	virtual						~DynamicOffsetGraphicsTestInstance	(void);
179 	void						init								(void);
180 	virtual tcu::TestStatus		iterate								(void);
181 	tcu::TestStatus				verifyImage							(void);
182 
183 private:
184 	const tcu::UVec2					m_renderSize;
185 	const VkFormat						m_colorFormat;
186 	VkImageCreateInfo					m_colorImageCreateInfo;
187 	Move<VkImage>						m_colorImage;
188 	de::MovePtr<Allocation>				m_colorImageAlloc;
189 	Move<VkImageView>					m_colorAttachmentView;
190 	vector<VkRenderPassSp>				m_renderPasses;
191 	vector<VkFramebufferSp>				m_framebuffers;
192 	Move<VkShaderModule>				m_vertexShaderModule;
193 	Move<VkShaderModule>				m_fragmentShaderModule;
194 	Move<VkBuffer>						m_vertexBuffer;
195 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
196 	Move<VkBuffer>						m_buffer;
197 	de::MovePtr<Allocation>				m_bufferAlloc;
198 	vector<Move<VkDescriptorSetLayout>>	m_descriptorSetLayouts;
199 	Move<VkDescriptorPool>				m_descriptorPool;
200 	vector<Move<VkDescriptorSet>>		m_descriptorSets;
201 	Move<VkPipelineLayout>				m_pipelineLayout;
202 	vector<GraphicsPipelineWrapper>		m_graphicsPipelines;
203 	Move<VkCommandPool>					m_cmdPool;
204 	vector<VkCommandBufferSp>			m_cmdBuffers;
205 	vector<Vertex4RGBA>					m_vertices;
206 };
207 #ifndef CTS_USES_VULKANSC
DynamicOffsetGraphicsTestInstance(Context & context,const TestParams & params)208 DynamicOffsetGraphicsTestInstance::DynamicOffsetGraphicsTestInstance (Context& context, const TestParams& params)
209 	: DynamicOffsetTestInstance	(context, params)
210 	, m_renderSize				(32, 32)
211 	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
212 	, m_vertices				(createQuads(m_params.numDescriptorSetBindings * m_params.numCmdBuffers, 0.25f))
213 {
214 }
215 #endif // CTS_USES_VULKANSC
216 
init(void)217 void DynamicOffsetGraphicsTestInstance::init (void)
218 {
219 	const VkComponentMapping		componentMappingRGBA		= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
220 	const DeviceInterface&			vk							= m_context.getDeviceInterface();
221 	const VkDevice					vkDevice					= m_context.getDevice();
222 	const deUint32					queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
223 	const deUint32					numBindings					= m_params.numDynamicBindings + m_params.numNonDynamicBindings;
224 	deUint32						offset						= 0;
225 	deUint32						quadNdx						= 0;
226 	const VkPhysicalDeviceLimits	deviceLimits				= getPhysicalDeviceProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()).limits;
227 	const VkDeviceSize				alignment					= ((m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ? deviceLimits.minUniformBufferOffsetAlignment : deviceLimits.minStorageBufferOffsetAlignment);
228 	const VkDeviceSize				extraBytes					= kColorSize % alignment;
229 	const VkDeviceSize				colorBlockInputSize			= ((extraBytes == 0ull) ? kColorSize : (kColorSize + alignment - extraBytes));
230 	const VkDeviceSize				bufferSize					= colorBlockInputSize * kNumTestColors;
231 	const VkDeviceSize				bindingOffset				= bufferSize / numBindings;
232 	const VkDescriptorType			nonDynamicDescriptorType	= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
233 
234 	vector<VkDescriptorSetLayout>	descriptorSetLayoutsPlain;
235 	vector<VkDescriptorSet>			descriptorSetsPlain;
236 
237 	// Create color image
238 	{
239 
240 		const VkImageCreateInfo colorImageParams =
241 		{
242 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
243 			DE_NULL,																// const void*				pNext;
244 			0u,																		// VkImageCreateFlags		flags;
245 			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
246 			m_colorFormat,															// VkFormat					format;
247 			{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
248 			1u,																		// deUint32					mipLevels;
249 			1u,																		// deUint32					arrayLayers;
250 			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
251 			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
252 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
253 			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
254 			1u,																		// deUint32					queueFamilyIndexCount;
255 			&queueFamilyIndex,														// const deUint32*			pQueueFamilyIndices;
256 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout			initialLayout;
257 		};
258 
259 		m_colorImageCreateInfo	= colorImageParams;
260 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
261 
262 		// Allocate and bind color image memory
263 		m_colorImageAlloc		= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
264 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
265 	}
266 
267 	// Create color attachment view
268 	{
269 		const VkImageViewCreateInfo colorAttachmentViewParams =
270 		{
271 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType				sType;
272 			DE_NULL,										// const void*					pNext;
273 			0u,												// VkImageViewCreateFlags		flags;
274 			*m_colorImage,									// VkImage						image;
275 			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType				viewType;
276 			m_colorFormat,									// VkFormat						format;
277 			componentMappingRGBA,							// VkChannelMapping				channels;
278 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange		subresourceRange;
279 		};
280 
281 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
282 	}
283 
284 	// Create render passes
285 	for (deUint32 renderPassIdx = 0; renderPassIdx < m_params.numCmdBuffers; renderPassIdx++)
286 	{
287 		// The first pass clears the output image, and the second one draws on top of the first pass.
288 		const VkAttachmentLoadOp		loadOps[]				=
289 		{
290 			VK_ATTACHMENT_LOAD_OP_CLEAR,
291 			VK_ATTACHMENT_LOAD_OP_LOAD
292 		};
293 
294 		const VkImageLayout				initialLayouts[]		=
295 		{
296 			VK_IMAGE_LAYOUT_UNDEFINED,
297 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
298 		};
299 
300 		const VkAttachmentDescription	attachmentDescription	=
301 		{
302 			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags
303 			m_colorFormat,								// VkFormat						format
304 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples
305 			loadOps[renderPassIdx],						// VkAttachmentLoadOp			loadOp
306 			VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp
307 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
308 			VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
309 			initialLayouts[renderPassIdx],				// VkImageLayout				initialLayout
310 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout
311 		};
312 
313 		const VkAttachmentReference		attachmentRef			=
314 		{
315 			0u,											// deUint32			attachment
316 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
317 		};
318 
319 		const VkSubpassDescription		subpassDescription		=
320 		{
321 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags	flags
322 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint			pipelineBindPoint
323 			0u,									// deUint32						inputAttachmentCount
324 			DE_NULL,							// const VkAttachmentReference*	pInputAttachments
325 			1u,									// deUint32						colorAttachmentCount
326 			&attachmentRef,						// const VkAttachmentReference*	pColorAttachments
327 			DE_NULL,							// const VkAttachmentReference*	pResolveAttachments
328 			DE_NULL,							// const VkAttachmentReference*	pDepthStencilAttachment
329 			0u,									// deUint32						preserveAttachmentCount
330 			DE_NULL								// const deUint32*				pPreserveAttachments
331 		};
332 
333 		const VkRenderPassCreateInfo	renderPassInfo			=
334 		{
335 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureTypei					sType
336 			DE_NULL,									// const void*						pNext
337 			(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
338 			1u,											// deUint32							attachmentCount
339 			&attachmentDescription,						// const VkAttachmentDescription*	pAttachments
340 			1u,											// deUint32							subpassCount
341 			&subpassDescription,						// const VkSubpassDescription*		pSubpasses
342 			0u,											// deUint32							dependencyCount
343 			DE_NULL										// const VkSubpassDependency*		pDependencies
344 		};
345 
346 		m_renderPasses.push_back(VkRenderPassSp(new Unique<VkRenderPass>(createRenderPass(vk, vkDevice, &renderPassInfo))));
347 	}
348 
349 	// Create framebuffers
350 	for (deUint32 framebufferIdx = 0; framebufferIdx < m_params.numCmdBuffers; framebufferIdx++)
351 	{
352 		const VkImageView				attachmentBindInfos[]	=
353 		{
354 			*m_colorAttachmentView
355 		};
356 
357 		const VkFramebufferCreateInfo	framebufferParams		=
358 		{
359 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType				sType;
360 			DE_NULL,									// const void*					pNext;
361 			0u,											// VkFramebufferCreateFlags		flags;
362 			**m_renderPasses[framebufferIdx],			// VkRenderPass					renderPass;
363 			1u,											// deUint32						attachmentCount;
364 			attachmentBindInfos,						// const VkImageView*			pAttachments;
365 			(deUint32)m_renderSize.x(),					// deUint32						width;
366 			(deUint32)m_renderSize.y(),					// deUint32						height;
367 			1u											// deUint32						layers;
368 		};
369 
370 		m_framebuffers.push_back(VkFramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vk, vkDevice, &framebufferParams))));
371 	}
372 
373 	// Create pipeline layout
374 	{
375 		// Create descriptor set layouts
376 		vector<VkDescriptorSetLayoutBinding>	descriptorSetLayoutBindings;
377 
378 		for (deUint32 binding = 0; binding < numBindings; binding++)
379 		{
380 			const bool								dynamicDesc						= (binding < m_params.numDynamicBindings);
381 			const VkDescriptorType					descriptorType					= (dynamicDesc ? m_params.descriptorType : nonDynamicDescriptorType);
382 			const deUint32							bindingNumber					= (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET ? binding : 0u);
383 			const deUint32							descriptorCount					= ((m_params.groupingStrategy == GroupingStrategy::ARRAYS) ? (dynamicDesc ? m_params.numDynamicBindings : m_params.numNonDynamicBindings) : 1u);
384 			const VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding		=
385 			{
386 				bindingNumber,				// uint32_t				binding;
387 				descriptorType,				// VkDescriptorType		descriptorType;
388 				descriptorCount,			// uint32_t				descriptorCount;
389 				VK_SHADER_STAGE_VERTEX_BIT,	// VkShaderStageFlags	stageFlags;
390 				DE_NULL						// const VkSampler*		pImmutableSamplers;
391 			};
392 
393 			// Skip used descriptors in array mode.
394 			if (m_params.groupingStrategy == GroupingStrategy::ARRAYS)
395 				binding = (dynamicDesc ? m_params.numDynamicBindings - 1 : numBindings);
396 
397 			descriptorSetLayoutBindings.push_back(descriptorSetLayoutBinding);
398 		}
399 
400 		vector<VkDescriptorSetLayoutCreateInfo> descriptorSetLayoutCreateInfos;
401 
402 		if (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET)
403 		{
404 			const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
405 			{
406 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType;
407 				DE_NULL,												// const void*							pNext;
408 				0u,														// VkDescriptorSetLayoutCreateFlags		flags;
409 				numBindings,											// uint32_t								bindingCount;
410 				descriptorSetLayoutBindings.data()						// const VkDescriptorSetLayoutBinding*	pBindings;
411 			};
412 
413 			m_descriptorSetLayouts.push_back(createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutCreateInfo));
414 		}
415 		else
416 		{
417 			for (size_t i = 0; i < descriptorSetLayoutBindings.size(); ++i)
418 			{
419 				const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
420 				{
421 					VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType;
422 					DE_NULL,												// const void*							pNext;
423 					0u,														// VkDescriptorSetLayoutCreateFlags		flags;
424 					1u,														// uint32_t								bindingCount;
425 					&descriptorSetLayoutBindings[i]							// const VkDescriptorSetLayoutBinding*	pBindings;
426 				};
427 
428 				m_descriptorSetLayouts.push_back(createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutCreateInfo));
429 			}
430 		}
431 
432 		// Create pipeline layout
433 		descriptorSetLayoutsPlain.resize(m_descriptorSetLayouts.size());
434 		for (size_t i = 0; i < descriptorSetLayoutsPlain.size(); ++i)
435 			descriptorSetLayoutsPlain[i] = m_descriptorSetLayouts[i].get();
436 
437 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams			=
438 		{
439 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// VkStructureType				sType;
440 			DE_NULL,													// const void*					pNext;
441 			0u,															// VkPipelineLayoutCreateFlags	flags;
442 			static_cast<deUint32>(descriptorSetLayoutsPlain.size()),	// deUint32						descriptorSetCount;
443 			descriptorSetLayoutsPlain.data(),							// const VkDescriptorSetLayout*	pSetLayouts;
444 			0u,															// deUint32						pushConstantRangeCount;
445 			DE_NULL														// const VkPushDescriptorRange*	pPushDescriptorRanges;
446 		};
447 
448 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
449 	}
450 
451 	// Create buffer
452 	{
453 		vector<deUint8> hostBuffer((size_t)bufferSize, 0);
454 		for (deUint32 colorIdx = 0; colorIdx < kNumTestColors; colorIdx++)
455 			deMemcpy(&hostBuffer[(deUint32)colorBlockInputSize * colorIdx], &testColors[colorIdx], kColorSize);
456 
457 		const VkBufferUsageFlags	usageFlags			= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
458 
459 		const VkBufferCreateInfo	bufferCreateInfo	=
460 		{
461 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
462 			DE_NULL,								// const void*			pNext;
463 			0u,										// VkBufferCreateFlags	flags
464 			bufferSize,								// VkDeviceSize			size;
465 			usageFlags,								// VkBufferUsageFlags	usage;
466 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
467 			1u,										// deUint32				queueFamilyCount;
468 			&queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
469 		};
470 
471 		m_buffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
472 		m_bufferAlloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_buffer), MemoryRequirement::HostVisible);
473 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_buffer, m_bufferAlloc->getMemory(), m_bufferAlloc->getOffset()));
474 
475 		deMemcpy(m_bufferAlloc->getHostPtr(), hostBuffer.data(), (size_t)bufferSize);
476 		flushAlloc(vk, vkDevice, *m_bufferAlloc);
477 	}
478 
479 	// Create descriptor pool
480 	{
481 		DescriptorPoolBuilder	poolBuilder;
482 		poolBuilder.addType(m_params.descriptorType, m_params.numDynamicBindings);
483 		poolBuilder.addType(nonDynamicDescriptorType, m_params.numNonDynamicBindings);
484 		m_descriptorPool = poolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, static_cast<deUint32>(m_descriptorSetLayouts.size()));
485 	}
486 
487 	// Create descriptor sets
488 	{
489 		for (size_t i = 0; i < m_descriptorSetLayouts.size(); ++i)
490 		{
491 			const VkDescriptorSetAllocateInfo allocInfo =
492 			{
493 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType					sType;
494 				DE_NULL,										// const void*						pNext;
495 				*m_descriptorPool,								// VkDescriptorPool					descriptorPool;
496 				1u,												// deUint32							setLayoutCount;
497 				&(m_descriptorSetLayouts[i].get()),				// const VkDescriptorSetLayout*		pSetLayouts;
498 			};
499 			m_descriptorSets.push_back(allocateDescriptorSet(vk, vkDevice, &allocInfo));
500 		}
501 	}
502 
503 	descriptorSetsPlain.resize(m_descriptorSets.size());
504 	for (size_t i = 0; i < descriptorSetsPlain.size(); ++i)
505 		descriptorSetsPlain[i] = m_descriptorSets[i].get();
506 
507 	// Update descriptor sets
508 	for (deUint32 binding = 0; binding < numBindings; ++binding)
509 	{
510 		const bool						dynamicDesc				= (binding < m_params.numDynamicBindings);
511 		const VkDescriptorType			descriptorType			= (dynamicDesc ? m_params.descriptorType : nonDynamicDescriptorType);
512 		const VkDescriptorBufferInfo	descriptorBufferInfo	=
513 		{
514 			*m_buffer,					// VkBuffer			buffer;
515 			bindingOffset * binding,	// VkDeviceSize		offset;
516 			kColorSize					// VkDeviceSize		range;
517 		};
518 
519 		VkDescriptorSet	bindingSet;
520 		deUint32		bindingNumber;
521 		deUint32		dstArrayElement;
522 
523 		if (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET)
524 		{
525 			bindingSet		= m_descriptorSets[0].get();
526 			bindingNumber	= binding;
527 			dstArrayElement	= 0u;
528 		}
529 		else if (m_params.groupingStrategy == GroupingStrategy::MULTISET)
530 		{
531 			bindingSet		= m_descriptorSets[binding].get();
532 			bindingNumber	= 0u;
533 			dstArrayElement	= 0u;
534 		}
535 		else // GroupingStrategy::ARRAYS
536 		{
537 			bindingSet		= (dynamicDesc ? m_descriptorSets[0].get() : m_descriptorSets[1].get());
538 			bindingNumber	= 0u;
539 			dstArrayElement	= (dynamicDesc ? binding : (binding - m_params.numDynamicBindings));
540 		}
541 
542 		const VkWriteDescriptorSet		writeDescriptorSet		=
543 		{
544 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
545 			DE_NULL,								// const void*						pNext;
546 			bindingSet,								// VkDescriptorSet					dstSet;
547 			bindingNumber,							// uint32_t							dstBinding;
548 			dstArrayElement,						// uint32_t							dstArrayElement;
549 			1u,										// uint32_t							descriptorCount;
550 			descriptorType,							// VkDescriptorType					descriptorType;
551 			DE_NULL,								// const VkDescriptorImageInfo*		pImageInfo;
552 			&descriptorBufferInfo,					// const VkDescriptorBufferInfo*	pBufferInfo;
553 			DE_NULL									// const VkBufferView*				pTexelBufferView;
554 		};
555 
556 		vk.updateDescriptorSets(vkDevice, 1u, &writeDescriptorSet, 0u, DE_NULL);
557 	}
558 
559 	// Create shaders
560 	{
561 		m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0u);
562 		m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0u);
563 	}
564 
565 	// Create pipelines
566 	m_graphicsPipelines.reserve(m_params.numCmdBuffers);
567 	for (deUint32 pipelineIdx = 0; pipelineIdx < m_params.numCmdBuffers; pipelineIdx++)
568 	{
569 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
570 		{
571 			0u,							// deUint32					binding;
572 			sizeof(Vertex4RGBA),		// deUint32					strideInBytes;
573 			VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputStepRate	stepRate;
574 		};
575 
576 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[]	=
577 		{
578 			{
579 				0u,									// deUint32	location;
580 				0u,									// deUint32	binding;
581 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
582 				0u									// deUint32	offsetInBytes;
583 			},
584 			{
585 				1u,									// deUint32	location;
586 				0u,									// deUint32	binding;
587 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
588 				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
589 			}
590 		};
591 
592 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams
593 		{
594 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
595 			DE_NULL,													// const void*								pNext;
596 			0u,															// vkPipelineVertexInputStateCreateFlags	flags;
597 			1u,															// deUint32									bindingCount;
598 			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
599 			2u,															// deUint32									attributeCount;
600 			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
601 		};
602 
603 		const vector<VkViewport>	viewports	{ makeViewport(m_renderSize) };
604 		const vector<VkRect2D>		scissors	{ makeRect2D(m_renderSize) };
605 
606 		m_graphicsPipelines.emplace_back(vk, vkDevice, m_params.pipelineConstructionType);
607 		m_graphicsPipelines.back().setMonolithicPipelineLayout(*m_pipelineLayout)
608 								  .setDefaultRasterizationState()
609 								  .setDefaultDepthStencilState()
610 								  .setDefaultColorBlendState()
611 								  .setDefaultMultisampleState()
612 								  .setupVertexInputState(&vertexInputStateParams)
613 								  .setupPreRasterizationShaderState(viewports,
614 																	scissors,
615 																	*m_pipelineLayout,
616 																	**m_renderPasses[pipelineIdx],
617 																	0u,
618 																	*m_vertexShaderModule)
619 								  .setupFragmentShaderState(*m_pipelineLayout, **m_renderPasses[pipelineIdx], 0u, *m_fragmentShaderModule)
620 								  .setupFragmentOutputState(**m_renderPasses[pipelineIdx])
621 								  .buildPipeline();
622 	}
623 
624 	// Create vertex buffer
625 	{
626 		const VkBufferCreateInfo vertexBufferParams =
627 		{
628 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
629 			DE_NULL,													// const void*			pNext;
630 			0u,															// VkBufferCreateFlags	flags;
631 			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
632 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
633 			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
634 			1u,															// deUint32				queueFamilyCount;
635 			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
636 		};
637 
638 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
639 		m_vertexBufferAlloc	= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
640 
641 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
642 
643 		// Load vertices into vertex buffer
644 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
645 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
646 	}
647 
648 	// Create command pool
649 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
650 
651 	// Create command buffers
652 	for (deUint32 cmdBufferIdx = 0; cmdBufferIdx < m_params.numCmdBuffers; cmdBufferIdx++)
653 		m_cmdBuffers.push_back(VkCommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY))));
654 
655 	for (deUint32 cmdBufferIdx = 0; cmdBufferIdx < m_params.numCmdBuffers; cmdBufferIdx++)
656 	{
657 		const VkClearValue	attachmentClearValue	= defaultClearValue(m_colorFormat);
658 		const VkDeviceSize	vertexBufferOffset		= 0;
659 		const deUint32		idx						= m_params.reverseOrder ? m_params.numCmdBuffers - cmdBufferIdx - 1 : cmdBufferIdx;
660 
661 		beginCommandBuffer(vk, **m_cmdBuffers[idx], 0u);
662 		beginRenderPass(vk, **m_cmdBuffers[idx], **m_renderPasses[idx], **m_framebuffers[idx], makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
663 		vk.cmdBindPipeline(**m_cmdBuffers[idx], VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipelines[idx].getPipeline());
664 		vk.cmdBindVertexBuffers(**m_cmdBuffers[idx], 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
665 
666 		for (deUint32 i = 0; i < m_params.numDescriptorSetBindings; i++)
667 		{
668 			vector<deUint32>	offsets;
669 			for (deUint32 dynamicBindingIdx = 0; dynamicBindingIdx < m_params.numDynamicBindings; dynamicBindingIdx++)
670 				offsets.push_back(offset + (deUint32)colorBlockInputSize * dynamicBindingIdx);
671 
672 			vk.cmdBindDescriptorSets(**m_cmdBuffers[idx], VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, static_cast<deUint32>(descriptorSetsPlain.size()), descriptorSetsPlain.data(), m_params.numDynamicBindings, offsets.data());
673 			offset += (deUint32)colorBlockInputSize;
674 
675 			// Draw quad
676 			vk.cmdDraw(**m_cmdBuffers[idx], 6, 1, 6 * quadNdx, 0);
677 			quadNdx++;
678 		}
679 
680 		endRenderPass(vk, **m_cmdBuffers[idx]);
681 		endCommandBuffer(vk, **m_cmdBuffers[idx]);
682 	}
683 }
684 
~DynamicOffsetGraphicsTestInstance(void)685 DynamicOffsetGraphicsTestInstance::~DynamicOffsetGraphicsTestInstance (void)
686 {
687 }
688 
iterate(void)689 tcu::TestStatus DynamicOffsetGraphicsTestInstance::iterate (void)
690 {
691 	init();
692 
693 	for (deUint32 cmdBufferIdx = 0; cmdBufferIdx < m_params.numCmdBuffers; cmdBufferIdx++)
694 		submitCommandsAndWait(m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(), **m_cmdBuffers[cmdBufferIdx]);
695 
696 	return verifyImage();
697 }
698 
verifyImage(void)699 tcu::TestStatus DynamicOffsetGraphicsTestInstance::verifyImage (void)
700 {
701 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(m_colorFormat);
702 	const tcu::TextureFormat	tcuDepthFormat		= tcu::TextureFormat();
703 	const ColorVertexShader		vertexShader;
704 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuDepthFormat);
705 	const rr::Program			program				(&vertexShader, &fragmentShader);
706 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
707 	bool						compareOk			= false;
708 
709 	// Render reference image
710 	{
711 		const deUint32	numBindings		= m_params.numDynamicBindings + m_params.numNonDynamicBindings;
712 		const deUint32	bindingOffset	= kNumTestColors / numBindings;
713 
714 		for (deUint32 quadIdx = 0; quadIdx < m_vertices.size() / 6; quadIdx++)
715 			for (deUint32 vertexIdx = 0; vertexIdx < 6; vertexIdx++)
716 			{
717 				tcu::Vec4 refColor(0.0f);
718 
719 				for (deUint32 binding = 0; binding < m_params.numDynamicBindings; binding++)
720 					refColor += testColors[quadIdx + binding * bindingOffset + binding];
721 				for (deUint32 binding = 0; binding < m_params.numNonDynamicBindings; binding++)
722 					refColor += testColors[(m_params.numDynamicBindings + binding) * bindingOffset];
723 				refColor.w() = 1.0f;
724 
725 				m_vertices[quadIdx * 6 + vertexIdx].color.xyzw() = refColor;
726 			}
727 
728 		refRenderer.draw(rr::RenderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits),
729 			             rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
730 	}
731 
732 	// Compare result with reference image
733 	{
734 		de::MovePtr<tcu::TextureLevel> result = readColorAttachment(
735 			m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(),
736 			m_context.getUniversalQueueFamilyIndex(), m_memAlloc, *m_colorImage, m_colorFormat, m_renderSize);
737 
738 		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
739 															  "IntImageCompare",
740 															  "Image comparison",
741 															  refRenderer.getAccess(),
742 															  result->getAccess(),
743 															  tcu::UVec4(2, 2, 2, 2),
744 															  tcu::IVec3(1, 1, 0),
745 															  true,
746 															  tcu::COMPARE_LOG_RESULT);
747 	}
748 
749 	if (compareOk)
750 		return tcu::TestStatus::pass("Result image matches reference");
751 	else
752 		return tcu::TestStatus::fail("Image mismatch");
753 }
754 #ifndef CTS_USES_VULKANSC
755 class DynamicOffsetGraphicsTest : public vkt::TestCase
756 {
757 public:
758 						DynamicOffsetGraphicsTest	(tcu::TestContext&	testContext,
759 													 const string&		name,
760 													 const string&		description,
761 													 const TestParams&	params);
762 						~DynamicOffsetGraphicsTest	(void);
763 	void				initPrograms				(SourceCollections& sourceCollections) const;
764 	TestInstance*		createInstance				(Context& context) const;
765 	void				checkSupport				(Context& context) const;
766 
767 protected:
768 	const TestParams	m_params;
769 };
770 
DynamicOffsetGraphicsTest(tcu::TestContext & testContext,const string & name,const string & description,const TestParams & params)771 DynamicOffsetGraphicsTest::DynamicOffsetGraphicsTest (tcu::TestContext&	testContext,
772 													  const string&		name,
773 													  const string&		description,
774 													  const TestParams&	params)
775 	: vkt::TestCase	(testContext, name, description)
776 	, m_params		(params)
777 {
778 }
779 
~DynamicOffsetGraphicsTest(void)780 DynamicOffsetGraphicsTest::~DynamicOffsetGraphicsTest (void)
781 {
782 }
783 
createInstance(Context & context) const784 TestInstance* DynamicOffsetGraphicsTest::createInstance (Context& context) const
785 {
786 	return new DynamicOffsetGraphicsTestInstance(context, m_params);
787 }
788 
checkSupport(Context & context) const789 void DynamicOffsetGraphicsTest::checkSupport(Context& context) const
790 {
791 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
792 }
793 
initPrograms(SourceCollections & sourceCollections) const794 void DynamicOffsetGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
795 {
796 	const deUint32	numBindings		= m_params.numDynamicBindings + m_params.numNonDynamicBindings;
797 	const string	bufferType		= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ? "uniform" : "readonly buffer";
798 	ostringstream	inputBlocks;
799 	ostringstream	inputSum;
800 	string			setAndBinding;
801 	string			blockSuffix;
802 	string			accessSuffix;
803 	bool			dynArrayDecl	= false;	// Dynamic descriptor block array declared?
804 	bool			nonDynArrayDecl	= false;	// Nondynamic descriptor block array declared?
805 
806 	for (deUint32 b = 0; b < numBindings; b++)
807 	{
808 		const bool		dynBind	= (b < m_params.numDynamicBindings);
809 		const string	bStr	= de::toString(b);
810 
811 		if (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET)
812 		{
813 			setAndBinding	= "set = 0, binding = " + bStr;
814 			blockSuffix		= bStr;
815 			accessSuffix	= bStr;
816 		}
817 		else if (m_params.groupingStrategy == GroupingStrategy::MULTISET)
818 		{
819 			setAndBinding	= "set = " + bStr + ", binding = 0";
820 			blockSuffix		= bStr;
821 			accessSuffix	= bStr;
822 		}
823 		else // GroupingStrategy::ARRAYS
824 		{
825 			// In array mode, only two sets are declared, one with an array of dynamic descriptors and another one with an array of
826 			// nondynamic descriptors.
827 			setAndBinding	= "set = " + string(dynBind ? "0" : "1") + ", binding = 0";
828 			blockSuffix		= string(dynBind ? "Dyn" : "NonDyn") + "[" + (dynBind ? de::toString(m_params.numDynamicBindings) : de::toString(m_params.numNonDynamicBindings)) + "]";
829 			accessSuffix	= string(dynBind ? "Dyn" : "NonDyn") + "[" + (dynBind ? de::toString(b) : de::toString(b - m_params.numDynamicBindings)) + "]";
830 		}
831 
832 		// In array mode, declare the input block only once per descriptor type.
833 		bool& arrayDeclFlag = (dynBind ? dynArrayDecl : nonDynArrayDecl);
834 		if (m_params.groupingStrategy != GroupingStrategy::ARRAYS || !arrayDeclFlag)
835 		{
836 			inputBlocks
837 				<< "layout(" << setAndBinding << ") " << bufferType << " Block" << bStr << "\n"
838 				<< "{\n"
839 				<< "    vec4 color;\n"
840 				<< "} inputData" << blockSuffix << ";\n"
841 				;
842 			arrayDeclFlag = true;
843 		}
844 
845 		// But the sum always needs to be added once per descriptor.
846 		inputSum << "    vtxColor.rgb += inputData" << accessSuffix << ".color.rgb;\n";
847 	}
848 
849 	const string	vertexSrc	=
850 		"#version 450\n"
851 		"layout(location = 0) in highp vec4 position;\n"
852 		"layout(location = 1) in highp vec4 color;\n"
853 		"layout(location = 0) out highp vec4 vtxColor;\n"
854 		+ inputBlocks.str() +
855 		"\n"
856 		"out gl_PerVertex { vec4 gl_Position; };\n"
857 		"\n"
858 		"void main()\n"
859 		"{\n"
860 		"    gl_Position = position;\n"
861 		"    vtxColor = vec4(0, 0, 0, 1);\n"
862 		+ inputSum.str() +
863 		"}\n";
864 
865 	const string	fragmentSrc	=
866 		"#version 450\n"
867 		"layout(location = 0) in highp vec4 vtxColor;\n"
868 		"layout(location = 0) out highp vec4 fragColor;\n"
869 		"\n"
870 		"void main (void)\n"
871 		"{\n"
872 		"    fragColor = vtxColor;\n"
873 		"}\n";
874 
875 	sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
876 	sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
877 }
878 #endif // CTS_USES_VULKANSC
879 class DynamicOffsetComputeTestInstance : public DynamicOffsetTestInstance
880 {
881 public:
882 								DynamicOffsetComputeTestInstance	(Context& context, const TestParams& params);
883 	virtual						~DynamicOffsetComputeTestInstance	(void);
884 	void						init								(void);
885 	virtual tcu::TestStatus		iterate								(void);
886 	tcu::TestStatus				verifyOutput						(void);
887 
888 private:
889 	const deUint32						m_numBindings;
890 	const deUint32						m_numOutputColors;
891 	const VkPhysicalDeviceLimits		m_deviceLimits;
892 	Move<VkShaderModule>				m_computeShaderModule;
893 	Move<VkBuffer>						m_buffer;
894 	de::MovePtr<Allocation>				m_bufferAlloc;
895 	vector<Move<VkDescriptorSetLayout>>	m_descriptorSetLayouts;
896 	Move<VkDescriptorPool>				m_descriptorPool;
897 	vector<Move<VkDescriptorSet>>		m_descriptorSets;
898 	Move<VkPipelineLayout>				m_pipelineLayout;
899 	Move<VkPipeline>					m_computePipeline;
900 	Move<VkBuffer>						m_outputBuffer;
901 	de::MovePtr<Allocation>				m_outputBufferAlloc;
902 	Move<VkCommandPool>					m_cmdPool;
903 	vector<VkCommandBufferSp>			m_cmdBuffers;
904 };
905 
DynamicOffsetComputeTestInstance(Context & context,const TestParams & params)906 DynamicOffsetComputeTestInstance::DynamicOffsetComputeTestInstance (Context& context, const TestParams& params)
907 	: DynamicOffsetTestInstance	(context, params)
908 	, m_numBindings				(params.numDynamicBindings + params.numNonDynamicBindings)
909 	, m_numOutputColors			(params.numCmdBuffers * params.numDescriptorSetBindings)
910 	, m_deviceLimits			(getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits)
911 {
912 }
913 
init(void)914 void DynamicOffsetComputeTestInstance::init (void)
915 {
916 	const DeviceInterface&			vk							= m_context.getDeviceInterface();
917 	const VkDevice					vkDevice					= m_context.getDevice();
918 	const deUint32					queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
919 	const VkDeviceSize				inputAlignment				= ((m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ? m_deviceLimits.minUniformBufferOffsetAlignment : m_deviceLimits.minStorageBufferOffsetAlignment);
920 	const VkDeviceSize				inputExtraBytes				= kColorSize % inputAlignment;
921 	const VkDeviceSize				colorBlockInputSize			= ((inputExtraBytes == 0ull) ? kColorSize : (kColorSize + inputAlignment - inputExtraBytes));
922 	const deUint32					colorBlockInputSizeU32		= static_cast<deUint32>(colorBlockInputSize);
923 	const VkDeviceSize				outputExtraBytes			= kColorSize % m_deviceLimits.minStorageBufferOffsetAlignment;
924 	const VkDeviceSize				colorBlockOutputSize		= ((outputExtraBytes == 0ull) ? kColorSize : (kColorSize + m_deviceLimits.minStorageBufferOffsetAlignment - outputExtraBytes));
925 	const deUint32					colorBlockOutputSizeU32		= static_cast<deUint32>(colorBlockOutputSize);
926 	const VkDeviceSize				bufferSize					= colorBlockInputSize * kNumTestColors;
927 	const VkDeviceSize				bindingOffset				= bufferSize / m_numBindings;
928 	const VkDescriptorType			nonDynamicDescriptorType	= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
929 	const VkDeviceSize				outputBufferSize			= colorBlockOutputSize * m_numOutputColors;
930 
931 	vector<VkDescriptorSetLayout>	descriptorSetLayoutsPlain;
932 	vector<VkDescriptorSet>			descriptorSetsPlain;
933 
934 	// Create pipeline layout
935 	{
936 		// Create descriptor set layouts
937 		vector<VkDescriptorSetLayoutBinding>	descriptorSetLayoutBindings;
938 
939 		for (deUint32 binding = 0; binding < m_numBindings; binding++)
940 		{
941 			const bool								dynamicDesc					= (binding < m_params.numDynamicBindings);
942 			const VkDescriptorType					descriptorType				= (dynamicDesc ? m_params.descriptorType : nonDynamicDescriptorType);
943 			const deUint32							bindingNumber				= (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET ? binding : 0u);
944 			const deUint32							descriptorCount				= ((m_params.groupingStrategy == GroupingStrategy::ARRAYS) ? (dynamicDesc ? m_params.numDynamicBindings : m_params.numNonDynamicBindings) : 1u);
945 			const VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding	=
946 			{
947 				bindingNumber,					// uint32_t				binding;
948 				descriptorType,					// VkDescriptorType		descriptorType;
949 				descriptorCount,				// uint32_t				descriptorCount;
950 				VK_SHADER_STAGE_COMPUTE_BIT,	// VkShaderStageFlags	stageFlags;
951 				DE_NULL							// const VkSampler*		pImmutableSamplers;
952 			};
953 
954 			// Skip used descriptors in array mode.
955 			if (m_params.groupingStrategy == GroupingStrategy::ARRAYS)
956 				binding = (dynamicDesc ? m_params.numDynamicBindings - 1 : m_numBindings);
957 
958 			descriptorSetLayoutBindings.push_back(descriptorSetLayoutBinding);
959 		}
960 
961 		const deUint32							bindingNumberOutput					= (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET ? m_numBindings : 0u);
962 		const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingOutput	=
963 		{
964 			bindingNumberOutput,						// uint32_t				binding;
965 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,	// VkDescriptorType		descriptorType;
966 			1u,											// uint32_t				descriptorCount;
967 			VK_SHADER_STAGE_COMPUTE_BIT,				// VkShaderStageFlags	stageFlags;
968 			DE_NULL										// const VkSampler*		pImmutableSamplers;
969 		};
970 
971 		descriptorSetLayoutBindings.push_back(descriptorSetLayoutBindingOutput);
972 
973 		if (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET)
974 		{
975 			const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
976 			{
977 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType;
978 				DE_NULL,												// const void*							pNext;
979 				0u,														// VkDescriptorSetLayoutCreateFlags		flags;
980 				m_numBindings + 1,										// uint32_t								bindingCount;
981 				descriptorSetLayoutBindings.data()						// const VkDescriptorSetLayoutBinding*	pBindings;
982 			};
983 
984 			m_descriptorSetLayouts.push_back(createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutCreateInfo, DE_NULL));
985 		}
986 		else
987 		{
988 			for (size_t i = 0; i < descriptorSetLayoutBindings.size(); ++i)
989 			{
990 				const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
991 				{
992 					VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType;
993 					DE_NULL,												// const void*							pNext;
994 					0u,														// VkDescriptorSetLayoutCreateFlags		flags;
995 					1u,														// uint32_t								bindingCount;
996 					&descriptorSetLayoutBindings[i]							// const VkDescriptorSetLayoutBinding*	pBindings;
997 				};
998 
999 				m_descriptorSetLayouts.push_back(createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutCreateInfo, DE_NULL));
1000 			}
1001 		}
1002 
1003 		// Create pipeline layout
1004 		descriptorSetLayoutsPlain.resize(m_descriptorSetLayouts.size());
1005 		for (size_t i = 0; i < descriptorSetLayoutsPlain.size(); ++i)
1006 			descriptorSetLayoutsPlain[i] = m_descriptorSetLayouts[i].get();
1007 
1008 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams			=
1009 		{
1010 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// VkStructureType				sType;
1011 			DE_NULL,													// const void*					pNext;
1012 			0u,															// VkPipelineLayoutCreateFlags	flags;
1013 			static_cast<deUint32>(descriptorSetLayoutsPlain.size()),	// deUint32						descriptorSetCount;
1014 			descriptorSetLayoutsPlain.data(),							// const VkDescriptorSetLayout*	pSetLayouts;
1015 			0u,															// deUint32						pushConstantRangeCount;
1016 			DE_NULL														// const VkPushDescriptorRange*	pPushDescriptorRanges;
1017 		};
1018 
1019 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1020 	}
1021 
1022 	// Create buffer
1023 	{
1024 		vector<deUint8> hostBuffer((deUint32)bufferSize, 0);
1025 		for (deUint32 colorIdx = 0; colorIdx < kNumTestColors; colorIdx++)
1026 			deMemcpy(&hostBuffer[colorBlockInputSizeU32 * colorIdx], &testColors[colorIdx], kColorSize);
1027 
1028 		const VkBufferUsageFlags	usageFlags			= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1029 
1030 		const VkBufferCreateInfo	bufferCreateInfo	=
1031 		{
1032 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
1033 			DE_NULL,								// const void*			pNext;
1034 			0u,										// VkBufferCreateFlags	flags
1035 			bufferSize,								// VkDeviceSize			size;
1036 			usageFlags,								// VkBufferUsageFlags	usage;
1037 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1038 			1u,										// deUint32				queueFamilyCount;
1039 			&queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
1040 		};
1041 
1042 		m_buffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
1043 		m_bufferAlloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_buffer), MemoryRequirement::HostVisible);
1044 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_buffer, m_bufferAlloc->getMemory(), m_bufferAlloc->getOffset()));
1045 
1046 		deMemcpy(m_bufferAlloc->getHostPtr(), hostBuffer.data(), (size_t)bufferSize);
1047 		flushAlloc(vk, vkDevice, *m_bufferAlloc);
1048 	}
1049 
1050 	// Create output buffer
1051 	{
1052 		const VkBufferCreateInfo bufferCreateInfo =
1053 		{
1054 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
1055 			DE_NULL,								// const void*			pNext;
1056 			0u,										// VkBufferCreateFlags	flags
1057 			outputBufferSize,						// VkDeviceSize			size;
1058 			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,		// VkBufferUsageFlags	usage;
1059 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1060 			1u,										// deUint32				queueFamilyCount;
1061 			&queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
1062 		};
1063 
1064 		m_outputBuffer		= createBuffer(vk, vkDevice, &bufferCreateInfo);
1065 		m_outputBufferAlloc	= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outputBuffer), MemoryRequirement::HostVisible);
1066 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outputBuffer, m_outputBufferAlloc->getMemory(), m_outputBufferAlloc->getOffset()));
1067 	}
1068 
1069 	// Create descriptor pool
1070 	{
1071 		DescriptorPoolBuilder	poolBuilder;
1072 		poolBuilder.addType(m_params.descriptorType, m_params.numDynamicBindings);
1073 		poolBuilder.addType(nonDynamicDescriptorType, m_params.numNonDynamicBindings);
1074 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1u);
1075 		m_descriptorPool = poolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, static_cast<deUint32>(m_descriptorSetLayouts.size()));
1076 	}
1077 
1078 	// Create descriptor sets
1079 	{
1080 		for (size_t i = 0; i < m_descriptorSetLayouts.size(); ++i)
1081 		{
1082 			const VkDescriptorSetAllocateInfo allocInfo =
1083 			{
1084 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType				sType;
1085 				DE_NULL,										// const void*					pNext;
1086 				*m_descriptorPool,								// VkDescriptorPool				descriptorPool;
1087 				1u,												// deUint32						setLayoutCount;
1088 				&(m_descriptorSetLayouts[i].get()),				// const VkDescriptorSetLayout*	pSetLayouts;
1089 			};
1090 			m_descriptorSets.push_back(allocateDescriptorSet(vk, vkDevice, &allocInfo));
1091 		}
1092 	}
1093 
1094 	descriptorSetsPlain.resize(m_descriptorSets.size());
1095 	for (size_t i = 0; i < descriptorSetsPlain.size(); ++i)
1096 		descriptorSetsPlain[i] = m_descriptorSets[i].get();
1097 
1098 	// Update input buffer descriptors
1099 	for (deUint32 binding = 0; binding < m_numBindings; ++binding)
1100 	{
1101 		const bool						dynamicDesc				= (binding < m_params.numDynamicBindings);
1102 		const VkDescriptorType			descriptorType			= dynamicDesc ? m_params.descriptorType : nonDynamicDescriptorType;
1103 		const VkDescriptorBufferInfo	descriptorBufferInfo	=
1104 		{
1105 			*m_buffer,					// VkBuffer			buffer;
1106 			bindingOffset * binding,	// VkDeviceSize		offset;
1107 			kColorSize					// VkDeviceSize		range;
1108 		};
1109 
1110 		VkDescriptorSet	bindingSet;
1111 		deUint32		bindingNumber;
1112 		deUint32		dstArrayElement;
1113 
1114 		if (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET)
1115 		{
1116 			bindingSet		= m_descriptorSets[0].get();
1117 			bindingNumber	= binding;
1118 			dstArrayElement	= 0u;
1119 		}
1120 		else if (m_params.groupingStrategy == GroupingStrategy::MULTISET)
1121 		{
1122 			bindingSet		= m_descriptorSets[binding].get();
1123 			bindingNumber	= 0u;
1124 			dstArrayElement	= 0u;
1125 		}
1126 		else // GroupingStrategy::ARRAYS
1127 		{
1128 			bindingSet		= (dynamicDesc ? m_descriptorSets[0].get() : m_descriptorSets[1].get());
1129 			bindingNumber	= 0u;
1130 			dstArrayElement	= (dynamicDesc ? binding : (binding - m_params.numDynamicBindings));
1131 		}
1132 
1133 		const VkWriteDescriptorSet		writeDescriptorSet		=
1134 		{
1135 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
1136 			DE_NULL,								// const void*						pNext;
1137 			bindingSet,								// VkDescriptorSet					dstSet;
1138 			bindingNumber,							// uint32_t							dstBinding;
1139 			dstArrayElement,						// uint32_t							dstArrayElement;
1140 			1u,										// uint32_t							descriptorCount;
1141 			descriptorType,							// VkDescriptorType					descriptorType;
1142 			DE_NULL,								// const VkDescriptorImageInfo*		pImageInfo;
1143 			&descriptorBufferInfo,					// const VkDescriptorBufferInfo*	pBufferInfo;
1144 			DE_NULL									// const VkBufferView*				pTexelBufferView;
1145 		};
1146 
1147 		vk.updateDescriptorSets(vkDevice, 1u, &writeDescriptorSet, 0u, DE_NULL);
1148 	}
1149 
1150 	// Update output buffer descriptor
1151 	{
1152 		const VkDescriptorBufferInfo	descriptorBufferInfo	=
1153 		{
1154 			*m_outputBuffer,	// VkBuffer			buffer;
1155 			0u,					// VkDeviceSize		offset;
1156 			kColorSize			// VkDeviceSize		range;
1157 		};
1158 
1159 		VkDescriptorSet	bindingSet;
1160 		deUint32		bindingNumber;
1161 
1162 		if (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET)
1163 		{
1164 			bindingSet		= m_descriptorSets[0].get();
1165 			bindingNumber	= m_numBindings;
1166 		}
1167 		else if (m_params.groupingStrategy == GroupingStrategy::MULTISET)
1168 		{
1169 			bindingSet		= m_descriptorSets.back().get();
1170 			bindingNumber	= 0u;
1171 		}
1172 		else // GroupingStrategy::ARRAYS
1173 		{
1174 			bindingSet		= m_descriptorSets.back().get();
1175 			bindingNumber	= 0u;
1176 		}
1177 
1178 		const VkWriteDescriptorSet		writeDescriptorSet		=
1179 		{
1180 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType					sType;
1181 			DE_NULL,									// const void*						pNext;
1182 			bindingSet,									// VkDescriptorSet					dstSet;
1183 			bindingNumber,								// uint32_t							dstBinding;
1184 			0u,											// uint32_t							dstArrayElement;
1185 			1u,											// uint32_t							descriptorCount;
1186 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,	// VkDescriptorType					descriptorType;
1187 			DE_NULL,									// const VkDescriptorImageInfo*		pImageInfo;
1188 			&descriptorBufferInfo,						// const VkDescriptorBufferInfo*	pBufferInfo;
1189 			DE_NULL										// const VkBufferView*				pTexelBufferView;
1190 		};
1191 
1192 		vk.updateDescriptorSets(vkDevice, 1u, &writeDescriptorSet, 0u, DE_NULL);
1193 	}
1194 
1195 	// Create shader
1196 	{
1197 		m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0u);
1198 	}
1199 
1200 	// Create pipeline
1201 	{
1202 		const VkPipelineShaderStageCreateInfo	stageCreateInfo	=
1203 		{
1204 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
1205 			DE_NULL,												// const void*							pNext;
1206 			0u,														// VkPipelineShaderStageCreateFlags		flags;
1207 			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
1208 			*m_computeShaderModule,									// VkShaderModule						module;
1209 			"main",													// const char*							pName;
1210 			DE_NULL													// const VkSpecializationInfo*			pSpecializationInfo;
1211 		};
1212 
1213 		const VkComputePipelineCreateInfo		createInfo		=
1214 		{
1215 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType					sType;
1216 			DE_NULL,												// const void*						pNext;
1217 			0u,														// VkPipelineCreateFlags			flags;
1218 			stageCreateInfo,										// VkPipelineShaderStageCreateInfo	stage;
1219 			*m_pipelineLayout,										// VkPipelineLayout					layout;
1220 			(VkPipeline)0,											// VkPipeline						basePipelineHandle;
1221 			0u,														// int32_t							basePipelineIndex;
1222 		};
1223 
1224 		m_computePipeline = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &createInfo);
1225 	}
1226 
1227 	// Create command pool
1228 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1229 
1230 	// Create command buffers
1231 	for (deUint32 cmdBufferIdx = 0; cmdBufferIdx < m_params.numCmdBuffers; cmdBufferIdx++)
1232 		m_cmdBuffers.push_back(VkCommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY))));
1233 
1234 	deUint32 inputOffset	= 0u;
1235 	deUint32 outputOffset	= 0u;
1236 
1237 	for (deUint32 cmdBufferIdx = 0; cmdBufferIdx < m_params.numCmdBuffers; cmdBufferIdx++)
1238 	{
1239 		const deUint32 idx = m_params.reverseOrder ? m_params.numCmdBuffers - cmdBufferIdx - 1 : cmdBufferIdx;
1240 
1241 		beginCommandBuffer(vk, **m_cmdBuffers[idx], 0u);
1242 		vk.cmdBindPipeline(**m_cmdBuffers[idx], VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
1243 
1244 		for (deUint32 i = 0; i < m_params.numDescriptorSetBindings; i++)
1245 		{
1246 			// Create pipeline barrier
1247 			const vk::VkBufferMemoryBarrier bufferBarrier =
1248 				{
1249 					vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,					// VkStructureType	sType;
1250 					DE_NULL,														// const void*		pNext;
1251 					vk::VK_ACCESS_SHADER_WRITE_BIT,									// VkAccessFlags	srcAccessMask;
1252 					vk::VK_ACCESS_SHADER_WRITE_BIT | vk::VK_ACCESS_HOST_READ_BIT,	// VkAccessFlags	dstAccessMask;
1253 					VK_QUEUE_FAMILY_IGNORED,										// deUint32			srcQueueFamilyIndex;
1254 					VK_QUEUE_FAMILY_IGNORED,										// deUint32			dstQueueFamilyIndex;
1255 					*m_outputBuffer,												// VkBuffer			buffer;
1256 					outputOffset,													// VkDeviceSize		offset;
1257 					VK_WHOLE_SIZE													// VkDeviceSize		size;
1258 				};
1259 
1260 			vector<deUint32> offsets;
1261 
1262 			// Offsets for input buffers
1263 			for (deUint32 dynamicBindingIdx = 0; dynamicBindingIdx < m_params.numDynamicBindings; dynamicBindingIdx++)
1264 				offsets.push_back(inputOffset + colorBlockInputSizeU32 * dynamicBindingIdx);
1265 			inputOffset += colorBlockInputSizeU32;
1266 
1267 			// Offset for output buffer
1268 			offsets.push_back(outputOffset);
1269 			outputOffset += colorBlockOutputSizeU32;
1270 
1271 			vk.cmdBindDescriptorSets(**m_cmdBuffers[idx], VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, static_cast<deUint32>(descriptorSetsPlain.size()), descriptorSetsPlain.data(), (deUint32)offsets.size(), offsets.data());
1272 
1273 			// Dispatch
1274 			vk.cmdDispatch(**m_cmdBuffers[idx], 1, 1, 1);
1275 
1276 			vk.cmdPipelineBarrier(**m_cmdBuffers[idx], vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1277 		}
1278 
1279 		endCommandBuffer(vk, **m_cmdBuffers[idx]);
1280 	}
1281 }
1282 
~DynamicOffsetComputeTestInstance(void)1283 DynamicOffsetComputeTestInstance::~DynamicOffsetComputeTestInstance (void)
1284 {
1285 }
1286 
iterate(void)1287 tcu::TestStatus DynamicOffsetComputeTestInstance::iterate (void)
1288 {
1289 	init();
1290 
1291 	for (deUint32 cmdBufferIdx = 0; cmdBufferIdx < m_params.numCmdBuffers; cmdBufferIdx++)
1292 		submitCommandsAndWait(m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(), **m_cmdBuffers[cmdBufferIdx]);
1293 
1294 	return verifyOutput();
1295 }
1296 
verifyOutput(void)1297 tcu::TestStatus DynamicOffsetComputeTestInstance::verifyOutput (void)
1298 {
1299 	const deUint32		bindingOffset			= kNumTestColors / m_numBindings;
1300 	const deUint32		colorBlockOutputSize	= static_cast<deUint32>(de::max(kColorSize, m_deviceLimits.minStorageBufferOffsetAlignment));
1301 	vector<tcu::Vec4>	refColors				(m_numOutputColors);
1302 	vector<tcu::Vec4>	outColors				(m_numOutputColors);
1303 
1304 	for (deUint32 i = 0; i < m_numOutputColors; i++)
1305 	{
1306 		tcu::Vec4 refColor(0.0f);
1307 
1308 		for (deUint32 binding = 0; binding < m_params.numDynamicBindings; binding++)
1309 			refColor += testColors[i + binding * bindingOffset + binding];
1310 		for (deUint32 binding = 0; binding < m_params.numNonDynamicBindings; binding++)
1311 			refColor += testColors[(m_params.numDynamicBindings + binding) * bindingOffset];
1312 		refColor.w() = 1.0f;
1313 
1314 		refColors[i] = refColor;
1315 	}
1316 
1317 	invalidateAlloc(m_context.getDeviceInterface(), m_context.getDevice(), *m_outputBufferAlloc);
1318 
1319 	// Grab the output results using offset alignment
1320 	for (deUint32 i = 0; i < m_numOutputColors; i++)
1321 		outColors[i] = *(tcu::Vec4*)((deUint8*)m_outputBufferAlloc->getHostPtr() + colorBlockOutputSize * i);
1322 
1323 	// Verify results
1324 	for (deUint32 i = 0; i < m_numOutputColors; i++)
1325 		if (outColors[i] != refColors[i])
1326 			return tcu::TestStatus::fail("Output mismatch");
1327 
1328 	return tcu::TestStatus::pass("Output matches expected values");
1329 }
1330 
1331 class DynamicOffsetComputeTest : public vkt::TestCase
1332 {
1333 public:
1334 						DynamicOffsetComputeTest	(tcu::TestContext&	testContext,
1335 													 const string&		name,
1336 													 const string&		description,
1337 													 const TestParams&	params);
1338 						~DynamicOffsetComputeTest	(void);
1339 	void				initPrograms				(SourceCollections& sourceCollections) const;
1340 	TestInstance*		createInstance				(Context& context) const;
1341 
1342 protected:
1343 	const TestParams	m_params;
1344 };
1345 
DynamicOffsetComputeTest(tcu::TestContext & testContext,const string & name,const string & description,const TestParams & params)1346 DynamicOffsetComputeTest::DynamicOffsetComputeTest (tcu::TestContext&	testContext,
1347 													const string&		name,
1348 													const string&		description,
1349 													const TestParams&	params)
1350 	: vkt::TestCase	(testContext, name, description)
1351 	, m_params		(params)
1352 {
1353 }
1354 
~DynamicOffsetComputeTest(void)1355 DynamicOffsetComputeTest::~DynamicOffsetComputeTest (void)
1356 {
1357 }
1358 
createInstance(Context & context) const1359 TestInstance* DynamicOffsetComputeTest::createInstance (Context& context) const
1360 {
1361 	return new DynamicOffsetComputeTestInstance(context, m_params);
1362 }
1363 
initPrograms(SourceCollections & sourceCollections) const1364 void DynamicOffsetComputeTest::initPrograms (SourceCollections& sourceCollections) const
1365 {
1366 	const deUint32	numBindings		= m_params.numDynamicBindings + m_params.numNonDynamicBindings;
1367 	const string	bufferType		= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ? "uniform" : "buffer";
1368 	ostringstream	inputBlocks;
1369 	ostringstream	inputSum;
1370 	string			setAndBinding;
1371 	string			blockSuffix;
1372 	string			accessSuffix;
1373 	bool			dynArrayDecl	= false;	// Dynamic descriptor block array declared?
1374 	bool			nonDynArrayDecl	= false;	// Nondynamic descriptor block array declared?
1375 	string			bStr;
1376 
1377 	for (deUint32 b = 0; b < numBindings; b++)
1378 	{
1379 		const bool dynBind	= (b < m_params.numDynamicBindings);
1380 		bStr				= de::toString(b);
1381 
1382 		if (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET)
1383 		{
1384 			setAndBinding = "set = 0, binding = " + bStr;
1385 			blockSuffix		= bStr;
1386 			accessSuffix	= bStr;
1387 		}
1388 		else if (m_params.groupingStrategy == GroupingStrategy::MULTISET)
1389 		{
1390 			setAndBinding = "set = " + bStr + ", binding = 0";
1391 			blockSuffix		= bStr;
1392 			accessSuffix	= bStr;
1393 		}
1394 		else // GroupingStrategy::ARRAYS
1395 		{
1396 			// In array mode, only two sets are declared, one with an array of dynamic descriptors and another one with an array of
1397 			// nondynamic descriptors.
1398 			setAndBinding	= "set = " + string(dynBind ? "0" : "1") + ", binding = 0";
1399 			blockSuffix		= string(dynBind ? "Dyn" : "NonDyn") + "[" + (dynBind ? de::toString(m_params.numDynamicBindings) : de::toString(m_params.numNonDynamicBindings)) + "]";
1400 			accessSuffix	= string(dynBind ? "Dyn" : "NonDyn") + "[" + (dynBind ? de::toString(b) : de::toString(b - m_params.numDynamicBindings)) + "]";
1401 		}
1402 
1403 		// In array mode, declare the input block only once per descriptor type.
1404 		bool& arrayDeclFlag = (dynBind ? dynArrayDecl : nonDynArrayDecl);
1405 		if (m_params.groupingStrategy != GroupingStrategy::ARRAYS || !arrayDeclFlag)
1406 		{
1407 			inputBlocks
1408 				<< "layout(" << setAndBinding << ") " << bufferType << " Block" << bStr << "\n"
1409 				<< "{\n"
1410 				<< "    vec4 color;\n"
1411 				<< "} inputData" << blockSuffix << ";\n"
1412 				;
1413 			arrayDeclFlag = true;
1414 		}
1415 
1416 		// But the sum always needs to be added once per descriptor.
1417 		inputSum << "    outData.color.rgb += inputData" << accessSuffix << ".color.rgb;\n";
1418 	}
1419 
1420 	bStr = de::toString(numBindings);
1421 	if (m_params.groupingStrategy == GroupingStrategy::SINGLE_SET)
1422 	{
1423 		setAndBinding = "set = 0, binding = " + bStr;
1424 	}
1425 	else if (m_params.groupingStrategy == GroupingStrategy::MULTISET)
1426 	{
1427 		setAndBinding = "set = " + bStr + ", binding = 0";
1428 	}
1429 	else // GroupingStrategy::ARRAYS
1430 	{
1431 		// The output buffer goes to a separate set.
1432 		deUint32 usedSets = 0u;
1433 		if (dynArrayDecl)		++usedSets;
1434 		if (nonDynArrayDecl)	++usedSets;
1435 
1436 		setAndBinding = "set = " + de::toString(usedSets) + ", binding = 0";
1437 	}
1438 
1439 	const string	computeSrc	=
1440 		"#version 450\n"
1441 		+ inputBlocks.str() +
1442 		"layout(" + setAndBinding + ") writeonly buffer Output\n"
1443 		"{\n"
1444 		"	vec4 color;\n"
1445 		"} outData;\n"
1446 		"\n"
1447 		"void main()\n"
1448 		"{\n"
1449 		"    outData.color = vec4(0, 0, 0, 1);\n"
1450 		+ inputSum.str() +
1451 		"}\n";
1452 
1453 	sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
1454 }
1455 
1456 class DynamicOffsetMixedTestInstance : public vkt::TestInstance
1457 {
1458 public:
DynamicOffsetMixedTestInstance(Context & context,const tcu::IVec2 renderSize,const deUint32 numInstances,const bool testAllOffsets,const bool reverseOrder,const bool runComputeFirst,const deUint32 vertexOffset,const deUint32 sharedUboOffset,const deUint32 fragUboOffset,const deUint32 ssboReadOffset,const deUint32 ssboWriteOffset)1459 								DynamicOffsetMixedTestInstance	(Context&			context,
1460 																 const tcu::IVec2	renderSize,
1461 																 const deUint32		numInstances,
1462 																 const bool			testAllOffsets,
1463 																 const bool			reverseOrder,
1464 																 const bool			runComputeFirst,
1465 																 const deUint32		vertexOffset,
1466 																 const deUint32		sharedUboOffset,
1467 																 const deUint32		fragUboOffset,
1468 																 const deUint32		ssboReadOffset,
1469 																 const deUint32		ssboWriteOffset)
1470 																: vkt::TestInstance	(context)
1471 																, m_renderSize		(renderSize)
1472 																, m_numInstances	(numInstances)
1473 																, m_testAllOffsets	(testAllOffsets)
1474 																, m_reverseOrder	(reverseOrder)
1475 																, m_runComputeFirst	(runComputeFirst)
1476 																, m_vertexOffset	(vertexOffset)
1477 																, m_sharedUboOffset	(sharedUboOffset)
1478 																, m_fragUboOffset	(fragUboOffset)
1479 																, m_ssboReadOffset	(ssboReadOffset)
1480 																, m_ssboWriteOffset	(ssboWriteOffset)
1481 																{}
1482 
1483 								~DynamicOffsetMixedTestInstance	();
1484 
1485 	virtual tcu::TestStatus		iterate							(void);
1486 
1487 private:
1488 	struct VertexInfo
1489 	{
1490 		tcu::Vec4	position;
1491 		tcu::Vec4	color;
1492 	};
1493 
1494 	const VkFormat		OUTPUT_COLOR_FORMAT		= VK_FORMAT_R8G8B8A8_UNORM;
1495 
1496 	const tcu::IVec2	m_renderSize;
1497 	const deUint32		m_numInstances;
1498 	const bool			m_testAllOffsets;
1499 	const bool			m_reverseOrder;
1500 	const bool			m_runComputeFirst;
1501 	const deUint32		m_vertexOffset;
1502 	const deUint32		m_sharedUboOffset;
1503 	const deUint32		m_fragUboOffset;
1504 	const deUint32		m_ssboReadOffset;
1505 	const deUint32		m_ssboWriteOffset;
1506 };
1507 
~DynamicOffsetMixedTestInstance()1508 DynamicOffsetMixedTestInstance::~DynamicOffsetMixedTestInstance ()
1509 {
1510 }
1511 
iterate(void)1512 tcu::TestStatus DynamicOffsetMixedTestInstance::iterate (void)
1513 {
1514 	tcu::TestLog&											log						= m_context.getTestContext().getLog();
1515 	const DeviceInterface&									vk						= m_context.getDeviceInterface();
1516 	const VkDevice											device					= m_context.getDevice();
1517 	Allocator&												allocator				= m_context.getDefaultAllocator();
1518 	const deUint32											queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
1519 
1520 	// Create shaders
1521 	const Move<VkShaderModule>								vertexShaderModule		= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u);
1522 	const Move<VkShaderModule>								fragmentShaderModule	= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
1523 	const Move<VkShaderModule>								computeShaderModule		= createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u);
1524 
1525 	const deUint32											vertexBufferBindId		= 0u;
1526 
1527 	// Vertex input state and binding
1528 	VkVertexInputBindingDescription							bindingDescription
1529 	{
1530 		vertexBufferBindId,			// uint32_t				binding;
1531 		sizeof(VertexInfo),			// uint32_t				stride;
1532 		VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputRate	inputRate;
1533 	};
1534 
1535 	const std::array<VkVertexInputAttributeDescription, 2>	vertexAttributeDescs
1536 	{ {
1537 		VkVertexInputAttributeDescription
1538 		{
1539 			0u,								// uint32_t	location;
1540 			vertexBufferBindId,				// uint32_t	binding;
1541 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1542 			0u								// uint32_t	offset;
1543 		},
1544 
1545 		VkVertexInputAttributeDescription
1546 		{
1547 			1u,								// uint32_t	location;
1548 			vertexBufferBindId,				// uint32_t	binding;
1549 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1550 			deUint32(sizeof(float)) * 4u	// uint32_t	offset;
1551 		}
1552 	} };
1553 
1554 	const VkPipelineVertexInputStateCreateInfo				vertexInputStateCreateInfo
1555 	{
1556 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
1557 		DE_NULL,													// const void*								pNext;
1558 		0u,															// VkPipelineVertexInputStateCreateFlags	flags;
1559 		1u,															// uint32_t									vertexBindingDescriptionCount;
1560 		&bindingDescription,										// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1561 		static_cast<uint32_t>(vertexAttributeDescs.size()),			// uint32_t									vertexAttributeDescriptionCount;
1562 		vertexAttributeDescs.data()									// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1563 	};
1564 
1565 	// Descriptor pool and descriptor set
1566 	DescriptorPoolBuilder									poolBuilder;
1567 
1568 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3u);
1569 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 2u);
1570 
1571 	const Move<VkDescriptorPool>							descriptorPool			= poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1572 
1573 	DescriptorSetLayoutBuilder								layoutBuilderAttachments;
1574 	{
1575 		if (!m_reverseOrder)
1576 		{
1577 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_VERTEX_BIT);
1578 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT);
1579 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, VK_SHADER_STAGE_COMPUTE_BIT);
1580 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_FRAGMENT_BIT);
1581 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, VK_SHADER_STAGE_COMPUTE_BIT);
1582 		}
1583 		else
1584 		{
1585 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, VK_SHADER_STAGE_COMPUTE_BIT);
1586 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_FRAGMENT_BIT);
1587 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, VK_SHADER_STAGE_COMPUTE_BIT);
1588 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT);
1589 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_VERTEX_BIT);
1590 		}
1591 	}
1592 
1593 	const Move<VkDescriptorSetLayout>						descriptorSetLayout		= layoutBuilderAttachments.build(vk, device);
1594 
1595 	const Move<VkDescriptorSet>								descriptorSet			= makeDescriptorSet(vk, device, descriptorPool.get(), descriptorSetLayout.get());
1596 
1597 	Move<VkImage>											colorImage				= (makeImage(vk, device, makeImageCreateInfo(m_renderSize, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1598 
1599 	// Allocate and bind color image memory
1600 	const VkImageSubresourceRange							colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1601 	const UniquePtr<Allocation>								colorImageAlloc			(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1602 	Move<VkImageView>										colorImageView			= (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, OUTPUT_COLOR_FORMAT, colorSubresourceRange));
1603 
1604 	// Create renderpass
1605 	const VkAttachmentDescription							attachmentDescription	=
1606 	{
1607 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags
1608 		OUTPUT_COLOR_FORMAT,						// VkFormat						format
1609 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples
1610 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp
1611 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp
1612 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
1613 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
1614 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout				initialLayout
1615 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout
1616 	};
1617 
1618 	const VkAttachmentReference								attachmentReference		=
1619 	{
1620 		0u,											// deUint32			attachment
1621 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
1622 	};
1623 
1624 	const VkSubpassDescription								subpassDescription		=
1625 	{
1626 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags	flags
1627 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint			pipelineBindPoint
1628 		0u,									// deUint32						inputAttachmentCount
1629 		DE_NULL,							// const VkAttachmentReference*	pInputAttachments
1630 		1u,									// deUint32						colorAttachmentCount
1631 		&attachmentReference,				// const VkAttachmentReference*	pColorAttachments
1632 		DE_NULL,							// const VkAttachmentReference*	pResolveAttachments
1633 		DE_NULL,							// const VkAttachmentReference*	pDepthStencilAttachment
1634 		0u,									// deUint32						preserveAttachmentCount
1635 		DE_NULL								// const deUint32*				pPreserveAttachments
1636 	};
1637 
1638 	const VkRenderPassCreateInfo							renderPassInfo			=
1639 	{
1640 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureTypei					sType
1641 		DE_NULL,									// const void*						pNext
1642 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
1643 		1u,											// deUint32							attachmentCount
1644 		&attachmentDescription,						// const VkAttachmentDescription*	pAttachments
1645 		1u,											// deUint32							subpassCount
1646 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses
1647 		0u,											// deUint32							dependencyCount
1648 		DE_NULL										// const VkSubpassDependency*		pDependencies
1649 	};
1650 
1651 	Move<VkRenderPass>										renderPass				= createRenderPass(vk, device, &renderPassInfo);
1652 
1653 	// Create framebuffer
1654 	const VkImageView										attachmentBindInfos[]	=
1655 	{
1656 		*colorImageView
1657 	};
1658 
1659 	const VkFramebufferCreateInfo							framebufferCreateInfo	=
1660 	{
1661 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType				sType;
1662 		DE_NULL,									// const void*					pNext;
1663 		VkFramebufferCreateFlags(0),				// VkFramebufferCreateFlags		flags;
1664 		*renderPass,								// VkRenderPass					renderPass;
1665 		1u,											// deUint32						attachmentCount;
1666 		attachmentBindInfos,						// const VkImageView*			pAttachments;
1667 		(deUint32)m_renderSize.x(),					// deUint32						width;
1668 		(deUint32)m_renderSize.y(),					// deUint32						height;
1669 		1u											// deUint32						layers;
1670 	};
1671 
1672 	Move<VkFramebuffer>										framebuffer				= createFramebuffer(vk, device, &framebufferCreateInfo);
1673 
1674 	// Create pipeline layout
1675 	const VkPipelineLayoutCreateInfo						pipelineLayoutInfo		=
1676 	{
1677 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,			// VkStructureType				sType;
1678 		DE_NULL,												// const void*					pNext;
1679 		0u,														// VkPipelineLayoutCreateFlags	flags;
1680 		1u,														// deUint32						descriptorSetCount;
1681 		&descriptorSetLayout.get(),								// const VkDescriptorSetLayout*	pSetLayouts;
1682 		0u,														// deUint32						pushConstantRangeCount;
1683 		DE_NULL													// const VkPushDescriptorRange*	pPushDescriptorRanges;
1684 	};
1685 
1686 	Move<VkPipelineLayout>									pipelineLayout			= createPipelineLayout(vk, device, &pipelineLayoutInfo);
1687 
1688 	// Create graphics pipeline
1689 	const std::vector<VkViewport>							viewports(1, makeViewport(m_renderSize));
1690 	const std::vector<VkRect2D>								scissors(1, makeRect2D(m_renderSize));
1691 
1692 	Move<VkPipeline>										graphicsPipeline		= makeGraphicsPipeline(
1693 		vk,										// const DeviceInterface&						vk
1694 		device,									// const VkDevice								device
1695 		*pipelineLayout,						// const VkPipelineLayout						pipelineLayout
1696 		*vertexShaderModule,					// const VkShaderModule							vertexShaderModule
1697 		DE_NULL,								// const VkShaderModule							tessellationControlShaderModule
1698 		DE_NULL,								// const VkShaderModule							tessellationEvalShaderModule
1699 		DE_NULL,								// const VkShaderModule							geometryShaderModule
1700 		*fragmentShaderModule,					// const VkShaderModule							fragmentShaderModule
1701 		*renderPass,							// const VkRenderPass							renderPass
1702 		viewports,								// const std::vector<VkViewport>&				viewports
1703 		scissors,								// const std::vector<VkRect2D>&					scissors
1704 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
1705 		0u,										// const deUint32								subpass
1706 		0u,										// const deUint32								patchControlPoints
1707 		&vertexInputStateCreateInfo);			// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
1708 
1709 	// Create compute pipeline
1710 	const VkPipelineShaderStageCreateInfo					compPipStageCreateInfo	=
1711 	{
1712 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
1713 		DE_NULL,												// const void*							pNext;
1714 		0u,														// VkPipelineShaderStageCreateFlags		flags;
1715 		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
1716 		*computeShaderModule,									// VkShaderModule						module;
1717 		"main",													// const char*							pName;
1718 		DE_NULL													// const VkSpecializationInfo*			pSpecializationInfo;
1719 	};
1720 
1721 	const VkComputePipelineCreateInfo						compPipelinecreateInfo	=
1722 	{
1723 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType					sType;
1724 		DE_NULL,												// const void*						pNext;
1725 		0u,														// VkPipelineCreateFlags			flags;
1726 		compPipStageCreateInfo,									// VkPipelineShaderStageCreateInfo	stage;
1727 		*pipelineLayout,										// VkPipelineLayout					layout;
1728 		(VkPipeline)0,											// VkPipeline						basePipelineHandle;
1729 		0u,														// int32_t							basePipelineIndex;
1730 	};
1731 
1732 	Move<VkPipeline>										computePipeline			= createComputePipeline(vk, device, (vk::VkPipelineCache)0u, &compPipelinecreateInfo);
1733 
1734 	const VkQueue											queue					= m_context.getUniversalQueue();
1735 	const VkPhysicalDeviceLimits							deviceLimits			= getPhysicalDeviceProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()).limits;
1736 
1737 	// Create vertex buffer
1738 	const deUint32											numVertices				= 6;
1739 	const VkDeviceSize										vertexBufferSizeBytes	= 256;
1740 	const Unique<VkBuffer>									vertexBuffer			(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1741 	const de::UniquePtr<Allocation>							vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1742 
1743 	const deUint32											instanceSize			= (deUint32)std::sqrt(m_numInstances);
1744 	const float												posIncrement			= 1.0f / (float)m_numInstances * float(instanceSize);
1745 
1746 	// Result image has to be a square and multiple of 16.
1747 	DE_ASSERT(instanceSize * instanceSize == m_numInstances && m_numInstances % 16u == 0);
1748 
1749 	{
1750 		tcu::Vec4			vertexColor	= tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f);
1751 		VertexInfo*	const	pVertices	= reinterpret_cast<VertexInfo*>(vertexBufferAlloc->getHostPtr());
1752 
1753 		pVertices[0]	= { tcu::Vec4(posIncrement, -posIncrement, 0.0f, 1.0f),		vertexColor };
1754 		pVertices[1]	= { tcu::Vec4(-posIncrement, -posIncrement, 0.0f, 1.0f),	vertexColor };
1755 		pVertices[2]	= { tcu::Vec4(-posIncrement, posIncrement, 0.0f, 1.0f),		vertexColor };
1756 		pVertices[3]	= { tcu::Vec4(-posIncrement, posIncrement, 1.0f, 1.0f),		vertexColor };
1757 		pVertices[4]	= { tcu::Vec4(posIncrement, posIncrement, 1.0f, 1.0f),		vertexColor };
1758 		pVertices[5]	= { tcu::Vec4(posIncrement, -posIncrement, 1.0f, 1.0f),		vertexColor };
1759 
1760 		flushAlloc(vk, device, *vertexBufferAlloc);
1761 	}
1762 
1763 	// Prepare buffers
1764 	const vk::VkDeviceSize									minUboAlignment			= deviceLimits.minUniformBufferOffsetAlignment;
1765 	const deUint32											bufferElementSizeVec4	= (deUint32)sizeof(tcu::Vec4);
1766 	const deUint32											bufferElementSizeMat4	= (deUint32)sizeof(tcu::Mat4);
1767 	deUint32												dynamicAlignmentVec4	= bufferElementSizeVec4;
1768 	deUint32												dynamicAlignmentMat4	= bufferElementSizeMat4;
1769 
1770 	if (minUboAlignment > 0)
1771 	{
1772 		dynamicAlignmentVec4	= (dynamicAlignmentVec4 + (deUint32)minUboAlignment - 1) & ~((deUint32)minUboAlignment - 1);
1773 		dynamicAlignmentMat4	= (dynamicAlignmentMat4 + (deUint32)minUboAlignment - 1) & ~((deUint32)minUboAlignment - 1);
1774 	}
1775 
1776 	const deUint32											bufferSizeVec4			= m_numInstances * dynamicAlignmentVec4;
1777 	const deUint32											bufferSizeMat4			= m_numInstances * dynamicAlignmentMat4;
1778 
1779 	const Unique<VkBuffer>									uboBufferVertex			(makeBuffer(vk, device, bufferSizeVec4, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));
1780 	const Unique<VkBuffer>									uboBufferShared			(makeBuffer(vk, device, bufferSizeVec4, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));
1781 	const Unique<VkBuffer>									ssboBufferWrite			(makeBuffer(vk, device, bufferSizeVec4, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1782 	const Unique<VkBuffer>									uboBufferFrag			(makeBuffer(vk, device, bufferSizeMat4, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));
1783 	const Unique<VkBuffer>									ssboBufferRead			(makeBuffer(vk, device, bufferSizeMat4, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1784 
1785 	const UniquePtr<Allocation>								uboBufferAllocVertex	(bindBuffer(vk, device, allocator, *uboBufferVertex, MemoryRequirement::HostVisible));
1786 	const UniquePtr<Allocation>								uboBufferAllocShared	(bindBuffer(vk, device, allocator, *uboBufferShared, MemoryRequirement::HostVisible));
1787 	const UniquePtr<Allocation>								ssboBufferAllocWrite	(bindBuffer(vk, device, allocator, *ssboBufferWrite, MemoryRequirement::HostVisible));
1788 	const UniquePtr<Allocation>								uboBufferAllocFrag		(bindBuffer(vk, device, allocator, *uboBufferFrag, MemoryRequirement::HostVisible));
1789 	const UniquePtr<Allocation>								ssboBufferAllocRead		(bindBuffer(vk, device, allocator, *ssboBufferRead, MemoryRequirement::HostVisible));
1790 
1791 	const float												colorIncrement			= 1.0f / float(m_numInstances);
1792 
1793 	std::vector<tcu::Vec4>									constVertexOffsets;
1794 
1795 	deUint32												columnCount				= 0u;
1796 	float													columnOffset			= posIncrement;
1797 	float													rowOffset				= -1.0f + posIncrement;
1798 
1799 	for (deUint32 posId = 0; posId < m_numInstances; posId++)
1800 	{
1801 		constVertexOffsets.push_back(tcu::Vec4(-1.0f + columnOffset, rowOffset, 0.0f, 0.0f));
1802 
1803 		columnOffset += 2 * posIncrement;
1804 		columnCount++;
1805 
1806 		if (columnCount >= instanceSize)
1807 		{
1808 			columnCount		= 0;
1809 			columnOffset	= posIncrement;
1810 			rowOffset		 += 2 * posIncrement;
1811 		}
1812 	}
1813 
1814 	// Fill buffers
1815 	{
1816 		char*	pPosUboVertex	= static_cast<char*>(uboBufferAllocVertex->getHostPtr());
1817 		char*	pPosUboShared	= static_cast<char*>(uboBufferAllocShared->getHostPtr());
1818 		char*	pPosSsboWrite	= static_cast<char*>(ssboBufferAllocWrite->getHostPtr());
1819 		char*	pPosUboFrag		= static_cast<char*>(uboBufferAllocFrag->getHostPtr());
1820 		char*	pPosSsboRead	= static_cast<char*>(ssboBufferAllocRead->getHostPtr());
1821 
1822 		if (m_testAllOffsets)
1823 		{
1824 			for (deUint32 posId = 0; posId < m_numInstances; posId++)
1825 			{
1826 				const float	constFragMat[]		=
1827 				{
1828 					colorIncrement, colorIncrement, colorIncrement, colorIncrement,
1829 					colorIncrement, colorIncrement, colorIncrement, colorIncrement,
1830 					colorIncrement, colorIncrement, colorIncrement, colorIncrement,
1831 					colorIncrement, colorIncrement, colorIncrement, colorIncrement * float(posId + 1u)
1832 				};
1833 
1834 				const float	constReadMat[]		=
1835 				{
1836 					1.0f, 0.0f, 1.0f, 0.0f,
1837 					0.0f, 1.0f, 0.0f, 1.0f - colorIncrement * float(posId + 1u),
1838 					1.0f, 0.0f, 1.0f, 0.17f,
1839 					0.0f, 1.0f, 0.0f, 1.0f
1840 				};
1841 
1842 				*((tcu::Vec4*)pPosUboVertex)	= constVertexOffsets[posId];
1843 				*((tcu::Vec4*)pPosUboShared)	= tcu::Vec4(colorIncrement * float(posId + 1u), 0.0f, 0.0f, 1.0f);
1844 				*((tcu::Vec4*)pPosSsboWrite)	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1845 				*((tcu::Mat4*)pPosUboFrag)		= tcu::Mat4(constFragMat);
1846 				*((tcu::Mat4*)pPosSsboRead)		= tcu::Mat4(constReadMat);
1847 				pPosUboVertex					+= dynamicAlignmentVec4;
1848 				pPosUboShared					+= dynamicAlignmentVec4;
1849 				pPosSsboWrite					+= dynamicAlignmentVec4;
1850 				pPosUboFrag						+= dynamicAlignmentMat4;
1851 				pPosSsboRead					+= dynamicAlignmentMat4;
1852 			}
1853 		}
1854 		else
1855 		{
1856 			for (deUint32 posId = 0; posId < m_numInstances; posId++)
1857 			{
1858 				const float	constFragMat[]		=
1859 				{
1860 					0.0f, 0.0f, 0.0f, 0.0f,
1861 					0.0f, 0.0f, 0.0f, 0.0f,
1862 					0.0f, 0.0f, 0.0f, 0.0f,
1863 					0.0f, 0.0f, 0.0f, m_fragUboOffset == posId ? 1.0f : 0.0f
1864 				};
1865 
1866 				const float	constReadMat[]		=
1867 				{
1868 					0.0f, 0.0f, 0.0f, 0.0f,
1869 					0.0f, 0.0f, 0.0f, m_ssboReadOffset == posId ? 0.25f : 0.0f,
1870 					0.0f, 0.0f, 0.0f, m_ssboReadOffset == posId ? 0.17f : 0.0f,
1871 					0.0f, 0.0f, 0.0f, 0.0f
1872 				};
1873 
1874 				*((tcu::Vec4*)pPosUboVertex)	= constVertexOffsets[posId];
1875 				*((tcu::Vec4*)pPosUboShared)	= m_sharedUboOffset == posId ? tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f) : tcu::Vec4(0);
1876 				*((tcu::Vec4*)pPosSsboWrite)	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1877 				*((tcu::Mat4*)pPosUboFrag)		= tcu::Mat4(constFragMat);
1878 				*((tcu::Mat4*)pPosSsboRead)		= tcu::Mat4(constReadMat);
1879 				pPosUboVertex					+= dynamicAlignmentVec4;
1880 				pPosUboShared					+= dynamicAlignmentVec4;
1881 				pPosSsboWrite					+= dynamicAlignmentVec4;
1882 				pPosUboFrag						+= dynamicAlignmentMat4;
1883 				pPosSsboRead					+= dynamicAlignmentMat4;
1884 			}
1885 		}
1886 
1887 		flushAlloc(vk, device, *uboBufferAllocVertex);
1888 		flushAlloc(vk, device, *uboBufferAllocShared);
1889 		flushAlloc(vk, device, *ssboBufferAllocWrite);
1890 		flushAlloc(vk, device, *uboBufferAllocFrag);
1891 		flushAlloc(vk, device, *ssboBufferAllocRead);
1892 	}
1893 
1894 	const vk::VkDescriptorBufferInfo						uboInfoVertexVec		= makeDescriptorBufferInfo(*uboBufferVertex, 0u, bufferElementSizeVec4);
1895 	const vk::VkDescriptorBufferInfo						uboInfoVec				= makeDescriptorBufferInfo(*uboBufferShared, 0u, bufferElementSizeVec4);
1896 	const vk::VkDescriptorBufferInfo						ssboInfoVec				= makeDescriptorBufferInfo(*ssboBufferWrite, 0u, bufferElementSizeVec4);
1897 	const vk::VkDescriptorBufferInfo						uboInfoMat				= makeDescriptorBufferInfo(*uboBufferFrag, 0u, bufferElementSizeMat4);
1898 	const vk::VkDescriptorBufferInfo						ssboInfoMat				= makeDescriptorBufferInfo(*ssboBufferRead, 0u, bufferElementSizeMat4);
1899 
1900 	// Update descriptors
1901 	DescriptorSetUpdateBuilder								builder;
1902 
1903 	builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_reverseOrder ? 4u : 0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &uboInfoVertexVec);
1904 	builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_reverseOrder ? 3u : 1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &uboInfoVec);
1905 	builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(						2u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, &ssboInfoVec);
1906 	builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_reverseOrder ? 1u : 3u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &uboInfoMat);
1907 	builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_reverseOrder ? 0u : 4u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, &ssboInfoMat);
1908 	builder.update(vk, device);
1909 
1910 	// Command buffer
1911 	const Unique<VkCommandPool>								cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1912 	const Unique<VkCommandBuffer>							cmdBuffer				(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1913 
1914 	const VkDeviceSize										vertexBufferOffset		= 0u;
1915 
1916 	// Render result buffer
1917 	const VkDeviceSize										colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(OUTPUT_COLOR_FORMAT)) * static_cast<VkDeviceSize>(m_renderSize.x()) * static_cast<VkDeviceSize>(m_renderSize.y());
1918 	const Unique<VkBuffer>									colorBuffer				(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1919 	const UniquePtr<Allocation>								colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1920 
1921 	const VkClearValue										clearColorValue			= defaultClearValue(OUTPUT_COLOR_FORMAT);
1922 
1923 	bool													runGraphics				= !m_runComputeFirst;
1924 
1925 	for (int i = 0; i < 2; i++)
1926 	{
1927 		beginCommandBuffer(vk, *cmdBuffer);
1928 
1929 		if (runGraphics)
1930 		{
1931 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), clearColorValue);
1932 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1933 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1934 		}
1935 		else
1936 		{
1937 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
1938 		}
1939 
1940 		if (m_testAllOffsets)
1941 		{
1942 			for (deUint32 instance = 0; instance < m_numInstances; instance++)
1943 			{
1944 				deUint32				offsetVec4 = dynamicAlignmentVec4 * instance;
1945 				deUint32				offsetMat4 = dynamicAlignmentMat4 * instance;
1946 				std::vector<deUint32>	offsets;
1947 
1948 				offsets.push_back(m_reverseOrder ? offsetMat4 : offsetVec4);
1949 				offsets.push_back(m_reverseOrder ? offsetMat4 : offsetVec4);
1950 				offsets.push_back(offsetVec4);
1951 				offsets.push_back(m_reverseOrder ? offsetVec4 : offsetMat4);
1952 				offsets.push_back(m_reverseOrder ? offsetVec4 : offsetMat4);
1953 
1954 				if (runGraphics)
1955 				{
1956 					vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), (deUint32)offsets.size(), offsets.data());
1957 					vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1958 				}
1959 				else
1960 				{
1961 					vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), (deUint32)offsets.size(), offsets.data());
1962 					vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
1963 				}
1964 			}
1965 		}
1966 		else
1967 		{
1968 			std::vector<deUint32>	offsets;
1969 
1970 			offsets.push_back(m_reverseOrder ? dynamicAlignmentMat4 * m_ssboReadOffset : dynamicAlignmentVec4 * m_vertexOffset);
1971 			offsets.push_back(m_reverseOrder ? dynamicAlignmentMat4 * m_fragUboOffset : dynamicAlignmentVec4 * m_sharedUboOffset);
1972 			offsets.push_back(dynamicAlignmentVec4 * m_ssboWriteOffset);
1973 			offsets.push_back(m_reverseOrder ? dynamicAlignmentVec4 * m_sharedUboOffset : dynamicAlignmentMat4 * m_fragUboOffset);
1974 			offsets.push_back(m_reverseOrder ? dynamicAlignmentVec4 * m_vertexOffset : dynamicAlignmentMat4 * m_ssboReadOffset);
1975 
1976 			if (runGraphics)
1977 			{
1978 				vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), (deUint32)offsets.size(), offsets.data());
1979 				vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1980 			}
1981 			else
1982 			{
1983 				vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), (deUint32)offsets.size(), offsets.data());
1984 				vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
1985 			}
1986 		}
1987 
1988 		if (runGraphics)
1989 		{
1990 			endRenderPass(vk, *cmdBuffer);
1991 			copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, m_renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1992 		}
1993 
1994 		runGraphics = !runGraphics;
1995 
1996 		endCommandBuffer(vk, *cmdBuffer);
1997 
1998 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1999 		m_context.resetCommandPoolForVKSC(device, *cmdPool);
2000 	}
2001 
2002 	// Check result image
2003 	{
2004 		tcu::TextureLevel				referenceTexture	(mapVkFormat(OUTPUT_COLOR_FORMAT), m_renderSize.x(), m_renderSize.y());
2005 		const tcu::PixelBufferAccess	referenceAccess		= referenceTexture.getAccess();
2006 		const deUint32					segmentSize			= m_renderSize.x() / instanceSize;
2007 
2008 		// Create reference image
2009 		if (m_testAllOffsets)
2010 		{
2011 			for (int y = 0; y < m_renderSize.y(); ++y)
2012 			{
2013 				for (int x = 0; x < m_renderSize.x(); ++x)
2014 				{
2015 					// While running test for all offsets, we create a nice gradient-like color for the pixels.
2016 					float colorValue = (float)(y / segmentSize * instanceSize + x / segmentSize + 1u) * colorIncrement;
2017 
2018 					referenceAccess.setPixel(tcu::Vec4(colorValue, 0.5f, colorValue, 1.0f), x, y);
2019 				}
2020 			}
2021 		}
2022 		else
2023 		{
2024 			// At first we have to find a correct location for the drawn square.
2025 			const deUint32	segmentCountPerRow	= (deUint32)m_renderSize.x() / segmentSize;
2026 			const deUint32	offsetY				= m_vertexOffset > segmentCountPerRow ? m_vertexOffset / segmentCountPerRow : 0u;
2027 			const deUint32	offsetX				= offsetY > 0 ? m_vertexOffset - (segmentCountPerRow * offsetY) : m_vertexOffset;
2028 			const deUint32	pixelOffsetY		= segmentSize * offsetY;
2029 			const deUint32	pixelOffsetX		= segmentSize * offsetX;
2030 
2031 			for (int y = 0; y < m_renderSize.y(); ++y)
2032 			{
2033 				for (int x = 0; x < m_renderSize.x(); ++x)
2034 				{
2035 					float colorValueRed		= clearColorValue.color.float32[0];
2036 					float colorValueGreen	= clearColorValue.color.float32[1];
2037 					float colorValueBlue	= clearColorValue.color.float32[2];
2038 
2039 					// Next, we fill the correct number of pixels with test color.
2040 					if (x >= (int)pixelOffsetX && x < int(pixelOffsetX + segmentSize) && y >= (int)pixelOffsetY && y < int(pixelOffsetY + segmentSize))
2041 					{
2042 						// While running test only for one offset, the result color for pixel is constant.
2043 						colorValueRed	= 1.0f;
2044 						colorValueGreen	= 0.5f;
2045 						colorValueBlue	= colorValueRed;
2046 					}
2047 
2048 					referenceAccess.setPixel(tcu::Vec4(colorValueRed, colorValueGreen, colorValueBlue, 1.0f), x, y);
2049 				}
2050 			}
2051 		}
2052 
2053 		invalidateAlloc(vk, device, *colorBufferAlloc);
2054 
2055 		const tcu::ConstPixelBufferAccess resultPixelAccess(mapVkFormat(OUTPUT_COLOR_FORMAT), m_renderSize.x(), m_renderSize.y(), 1, colorBufferAlloc->getHostPtr());
2056 
2057 		if (!tcu::floatThresholdCompare(log, "color", "Image compare", referenceAccess, resultPixelAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT))
2058 			return tcu::TestStatus::fail("Rendered image is not correct");
2059 	}
2060 
2061 	// Check result buffer values
2062 	{
2063 		invalidateAlloc(vk, device, *ssboBufferAllocWrite);
2064 
2065 		std::vector<tcu::Vec4>	refColors;
2066 		std::vector<tcu::Vec4>	outColors;
2067 
2068 			for (deUint32 i = 0; i < m_numInstances; i++)
2069 			{
2070 				if (m_testAllOffsets)
2071 				{
2072 					refColors.push_back(tcu::Vec4(float(i + 1) * colorIncrement, 1.0f - float(i + 1) * colorIncrement, 0.17f, 1.0f));
2073 				}
2074 				else
2075 				{
2076 					refColors.push_back(m_ssboWriteOffset == i ? tcu::Vec4(1.0f, 0.25f, 0.17f, 1.0f) : tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
2077 				}
2078 
2079 				outColors.push_back(*(tcu::Vec4*)((deUint8*)ssboBufferAllocWrite->getHostPtr() + dynamicAlignmentVec4 * i));
2080 
2081 				if (!compareVectors(outColors[i], refColors[i], 0.01f))
2082 				{
2083 					log << tcu::TestLog::Message << "Reference: " << refColors[i].x() << ", " << refColors[i].y() << ", " << refColors[i].z() << ", " << refColors[i].w() << ", " << tcu::TestLog::EndMessage;
2084 					log << tcu::TestLog::Message << "Result   : " << outColors[i].x() << ", " << outColors[i].y() << ", " << outColors[i].z() << ", " << outColors[i].w() << ", " << tcu::TestLog::EndMessage;
2085 
2086 					return tcu::TestStatus::fail("Result value is not correct");
2087 				}
2088 			}
2089 		}
2090 
2091 	return tcu::TestStatus::pass("Success");
2092 }
2093 
2094 class DynamicOffsetMixedTest : public vkt::TestCase
2095 {
2096 public:
DynamicOffsetMixedTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const tcu::IVec2 renderSize,const deUint32 numInstances,const bool testAllOffsets,const bool reverseOrder,const bool runComputeFirst=false,const deUint32 vertexOffset=0u,const deUint32 sharedUboOffset=0u,const deUint32 fragUboOffset=0u,const deUint32 ssboReadOffset=0u,const deUint32 ssboWriteOffset=0u)2097 							DynamicOffsetMixedTest	(tcu::TestContext&	testContext,
2098 													 const std::string&	name,
2099 													 const std::string&	description,
2100 													 const tcu::IVec2	renderSize,
2101 													 const deUint32		numInstances,
2102 													 const bool			testAllOffsets,
2103 													 const bool			reverseOrder,
2104 													 const bool			runComputeFirst	= false,
2105 													 const deUint32		vertexOffset	= 0u,
2106 													 const deUint32		sharedUboOffset	= 0u,
2107 													 const deUint32		fragUboOffset	= 0u,
2108 													 const deUint32		ssboReadOffset	= 0u,
2109 													 const deUint32		ssboWriteOffset	= 0u)
2110 													: vkt::TestCase		(testContext, name, description)
2111 													, m_renderSize		(renderSize)
2112 													, m_numInstances	(numInstances)
2113 													, m_testAllOffsets	(testAllOffsets)
2114 													, m_reverseOrder	(reverseOrder)
2115 													, m_runComputeFirst	(runComputeFirst)
2116 													, m_vertexOffset	(vertexOffset)
2117 													, m_sharedUboOffset	(sharedUboOffset)
2118 													, m_fragUboOffset	(fragUboOffset)
2119 													, m_ssboReadOffset	(ssboReadOffset)
2120 													, m_ssboWriteOffset	(ssboWriteOffset)
2121 													{}
2122 
2123 						~DynamicOffsetMixedTest		(void);
2124 
2125 	void				initPrograms				(SourceCollections& sourceCollections) const;
2126 	TestInstance		*createInstance				(Context& context) const;
2127 private:
2128 	const tcu::IVec2	m_renderSize;
2129 	const deUint32		m_numInstances;
2130 	const bool			m_testAllOffsets;
2131 	const bool			m_reverseOrder;
2132 	const bool			m_runComputeFirst;
2133 	const deUint32		m_vertexOffset;
2134 	const deUint32		m_sharedUboOffset;
2135 	const deUint32		m_fragUboOffset;
2136 	const deUint32		m_ssboReadOffset;
2137 	const deUint32		m_ssboWriteOffset;
2138 };
2139 
~DynamicOffsetMixedTest(void)2140 DynamicOffsetMixedTest::~DynamicOffsetMixedTest (void)
2141 {
2142 }
2143 
initPrograms(SourceCollections & sourceCollections) const2144 void DynamicOffsetMixedTest::initPrograms (SourceCollections& sourceCollections) const
2145 {
2146 	// Vertex
2147 	{
2148 		std::ostringstream src;
2149 
2150 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2151 			<< "\n"
2152 			<< "layout(set = 0, binding = " << (m_reverseOrder ? "4" : "0") << ") uniform uboVertexData\n"
2153 			<< "{\n"
2154 			<< "	vec4 position;\n"
2155 			<< "} inputPosData;\n"
2156 			<< "\n"
2157 			<< "layout(location = 0) in vec4 inPosition;\n"
2158 			<< "layout(location = 1) in vec4 inColor;\n"
2159 			<< "layout(location = 0) out vec4 outColor;\n"
2160 			<< "\n"
2161 			<< "out gl_PerVertex\n"
2162 			<< "{\n"
2163 			<< "	vec4 gl_Position;\n"
2164 			<< "};\n"
2165 			<< "\n"
2166 			<< "void main (void)\n"
2167 			<< "{\n"
2168 			<< "	gl_Position = inPosition + inputPosData.position;\n"
2169 			<< "	outColor = inColor;\n"
2170 			<< "}\n";
2171 
2172 		sourceCollections.glslSources.add("vert") << glu::VertexSource(src.str());
2173 	}
2174 
2175 	// Fragment
2176 	{
2177 		std::ostringstream src;
2178 
2179 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2180 			<< "\n"
2181 			<< "layout(set = 0, binding = " << (m_reverseOrder ? "3" : "1") << ") uniform uboSharedData\n"
2182 			<< "{\n"
2183 			<< "	vec4 color;\n"
2184 			<< "} inputData0;\n"
2185 			<< "\n"
2186 			<< "layout(set = 0, binding = " << (m_reverseOrder ? "1" : "3") << ") uniform uboFragOnly\n"
2187 			<< "{\n"
2188 			<< "	mat4 color;\n"
2189 			<< "} inputData1;\n"
2190 			<< "\n"
2191 			<< "layout(location = 0) in vec4 inColor;\n"
2192 			<< "layout(location = 0) out vec4 outColor;\n"
2193 			<< "\n"
2194 			<< "void main (void)\n"
2195 			<< "{\n"
2196 			<< "	outColor = inColor + inputData0.color;\n"
2197 			<< "	outColor.b = inputData1.color[3][3];\n"
2198 			<< "}\n";
2199 
2200 		sourceCollections.glslSources.add("frag") << glu::FragmentSource(src.str());
2201 	}
2202 
2203 	// Compute
2204 	{
2205 		std::ostringstream src;
2206 
2207 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2208 			<< "\n"
2209 			<< "layout(set = 0, binding = " << (m_reverseOrder ? "3" : "1") << ") uniform uboSharedData\n"
2210 			<< "{\n"
2211 			<< "	vec4 color;\n"
2212 			<< "} inputData;\n"
2213 			<< "\n"
2214 			<< "layout(set = 0, binding = 2) writeonly buffer ssboOutput\n"
2215 			<< "{\n"
2216 			<< "	vec4 color;\n"
2217 			<< "} outData;\n"
2218 			<< "\n"
2219 			<< "layout(set = 0, binding = " << (m_reverseOrder ? "0" : "4") << ") readonly buffer ssboInput\n"
2220 			<< "{\n"
2221 			<< "	mat4 color;\n"
2222 			<< "} readData;\n"
2223 			<< "\n"
2224 			<< "void main (void)\n"
2225 			<< "{\n"
2226 			<< "	outData.color = inputData.color;\n"
2227 			<< "	outData.color.g = readData.color[3][1];\n"
2228 			<< "	outData.color.b = readData.color[3][2];\n"
2229 			<< "}\n";
2230 
2231 		sourceCollections.glslSources.add("comp") << glu::ComputeSource(src.str());
2232 	}
2233 }
2234 
createInstance(Context & context) const2235 TestInstance* DynamicOffsetMixedTest::createInstance (Context& context) const
2236 {
2237 	return new DynamicOffsetMixedTestInstance	(context,
2238 												 m_renderSize,
2239 												 m_numInstances,
2240 												 m_testAllOffsets,
2241 												 m_reverseOrder,
2242 												 m_runComputeFirst,
2243 												 m_vertexOffset,
2244 												 m_sharedUboOffset,
2245 												 m_fragUboOffset,
2246 												 m_ssboReadOffset,
2247 												 m_ssboWriteOffset);
2248 }
2249 
2250 } // anonymous
2251 
createDynamicOffsetTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2252 tcu::TestCaseGroup* createDynamicOffsetTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2253 {
2254 	const char*	pipelineTypes[]			= { "graphics", "compute" };
2255 
2256 	struct
2257 	{
2258 		const char*				name;
2259 		const GroupingStrategy	strategy;
2260 	}
2261 	const groupingTypes[]				=
2262 	{
2263 		{ "single_set",		GroupingStrategy::SINGLE_SET	},
2264 		{ "multiset",		GroupingStrategy::MULTISET		},
2265 		{ "arrays",			GroupingStrategy::ARRAYS		},
2266 	};
2267 
2268 	struct
2269 	{
2270 		const char*			name;
2271 		VkDescriptorType	type;
2272 	}
2273 	const descriptorTypes[]				=
2274 	{
2275 		{	"uniform_buffer",	VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC	},
2276 		{	"storage_buffer",	VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC	}
2277 	};
2278 
2279 	struct
2280 	{
2281 		const char*		name;
2282 		deUint32		num;
2283 	}
2284 	const numCmdBuffers[]				=
2285 	{
2286 		{	"numcmdbuffers_1",	1u	},
2287 		{	"numcmdbuffers_2",	2u	}
2288 	};
2289 
2290 	struct
2291 	{
2292 		const char*		name;
2293 		bool			reverse;
2294 	}
2295 	const reverseOrders[]				=
2296 	{
2297 		{	"reverseorder",	true	},
2298 		{	"sameorder",	false	}
2299 	};
2300 
2301 	struct
2302 	{
2303 		const char*		name;
2304 		deUint32		num;
2305 	}
2306 	const numDescriptorSetBindings[]	=
2307 	{
2308 		{	"numdescriptorsetbindings_1",	1u	},
2309 		{	"numdescriptorsetbindings_2",	2u	}
2310 	};
2311 
2312 	struct
2313 	{
2314 		const char*		name;
2315 		deUint32		num;
2316 	}
2317 	const numDynamicBindings[]			=
2318 	{
2319 		{	"numdynamicbindings_1",	1u	},
2320 		{	"numdynamicbindings_2",	2u	}
2321 	};
2322 
2323 	struct
2324 	{
2325 		const char*		name;
2326 		deUint32		num;
2327 	}
2328 	const numNonDynamicBindings[]		=
2329 	{
2330 		{	"numnondynamicbindings_0",	0u	},
2331 		{	"numnondynamicbindings_1",	1u	}
2332 	};
2333 
2334 	de::MovePtr<tcu::TestCaseGroup>	dynamicOffsetTests	(new tcu::TestCaseGroup(testCtx, "dynamic_offset", "Dynamic offset tests"));
2335 
2336 	for (deUint32 pipelineTypeIdx = 0; pipelineTypeIdx < DE_LENGTH_OF_ARRAY(pipelineTypes); pipelineTypeIdx++)
2337 	{
2338 		// VK_EXT_graphics_pipeline_library can't be tested with compute pipeline
2339 		if ((pipelineTypeIdx == 1) && (pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC))
2340 			continue;
2341 
2342 		de::MovePtr<tcu::TestCaseGroup>	pipelineTypeGroup	(new tcu::TestCaseGroup(testCtx, pipelineTypes[pipelineTypeIdx], ""));
2343 
2344 		for (deUint32 groupingTypeIdx = 0; groupingTypeIdx < DE_LENGTH_OF_ARRAY(groupingTypes); ++groupingTypeIdx)
2345 		{
2346 			de::MovePtr<tcu::TestCaseGroup> groupingTypeGroup (new tcu::TestCaseGroup(testCtx, groupingTypes[groupingTypeIdx].name, ""));
2347 
2348 			for (deUint32 descriptorTypeIdx = 0; descriptorTypeIdx < DE_LENGTH_OF_ARRAY(descriptorTypes); descriptorTypeIdx++)
2349 			{
2350 				de::MovePtr<tcu::TestCaseGroup>	descriptorTypeGroup	(new tcu::TestCaseGroup(testCtx, descriptorTypes[descriptorTypeIdx].name, ""));
2351 
2352 				for (deUint32 numCmdBuffersIdx = 0; numCmdBuffersIdx < DE_LENGTH_OF_ARRAY(numCmdBuffers); numCmdBuffersIdx++)
2353 				{
2354 					de::MovePtr<tcu::TestCaseGroup>	numCmdBuffersGroup	(new tcu::TestCaseGroup(testCtx, numCmdBuffers[numCmdBuffersIdx].name, ""));
2355 
2356 					for (deUint32 reverseOrderIdx = 0; reverseOrderIdx < DE_LENGTH_OF_ARRAY(reverseOrders); reverseOrderIdx++)
2357 					{
2358 						if (numCmdBuffers[numCmdBuffersIdx].num < 2 && reverseOrders[reverseOrderIdx].reverse)
2359 							continue;
2360 
2361 						de::MovePtr<tcu::TestCaseGroup>	reverseOrderGroup	(new tcu::TestCaseGroup(testCtx, reverseOrders[reverseOrderIdx].name, ""));
2362 
2363 						for (deUint32 numDescriptorSetBindingsIdx = 0; numDescriptorSetBindingsIdx < DE_LENGTH_OF_ARRAY(numDescriptorSetBindings); numDescriptorSetBindingsIdx++)
2364 						{
2365 							if (numCmdBuffers[numCmdBuffersIdx].num > 1 && numDescriptorSetBindings[numDescriptorSetBindingsIdx].num > 1)
2366 								continue;
2367 
2368 							de::MovePtr<tcu::TestCaseGroup>	numDescriptorSetBindingsGroup	(new tcu::TestCaseGroup(testCtx, numDescriptorSetBindings[numDescriptorSetBindingsIdx].name, ""));
2369 							for (deUint32 numDynamicBindingsIdx = 0; numDynamicBindingsIdx < DE_LENGTH_OF_ARRAY(numDynamicBindings); numDynamicBindingsIdx++)
2370 							{
2371 								de::MovePtr<tcu::TestCaseGroup>	numDynamicBindingsGroup	(new tcu::TestCaseGroup(testCtx, numDynamicBindings[numDynamicBindingsIdx].name, ""));
2372 
2373 								for (deUint32 numNonDynamicBindingsIdx = 0; numNonDynamicBindingsIdx < DE_LENGTH_OF_ARRAY(numNonDynamicBindings); numNonDynamicBindingsIdx++)
2374 								{
2375 									TestParams params
2376 									{
2377 										pipelineConstructionType,
2378 										descriptorTypes[descriptorTypeIdx].type,
2379 										numCmdBuffers[numCmdBuffersIdx].num,
2380 										reverseOrders[reverseOrderIdx].reverse,
2381 										numDescriptorSetBindings[numDescriptorSetBindingsIdx].num,
2382 										numDynamicBindings[numDynamicBindingsIdx].num,
2383 										numNonDynamicBindings[numNonDynamicBindingsIdx].num,
2384 										groupingTypes[groupingTypeIdx].strategy
2385 									};
2386 #ifndef CTS_USES_VULKANSC
2387 									if (strcmp(pipelineTypes[pipelineTypeIdx], "graphics") == 0)
2388 										numDynamicBindingsGroup->addChild(new DynamicOffsetGraphicsTest(testCtx, numNonDynamicBindings[numNonDynamicBindingsIdx].name, "", params));
2389 									else
2390 #endif // CTS_USES_VULKANSC
2391 										numDynamicBindingsGroup->addChild(new DynamicOffsetComputeTest(testCtx, numNonDynamicBindings[numNonDynamicBindingsIdx].name, "", params));
2392 								}
2393 
2394 								numDescriptorSetBindingsGroup->addChild(numDynamicBindingsGroup.release());
2395 							}
2396 
2397 							reverseOrderGroup->addChild(numDescriptorSetBindingsGroup.release());
2398 						}
2399 
2400 						numCmdBuffersGroup->addChild(reverseOrderGroup.release());
2401 					}
2402 
2403 					descriptorTypeGroup->addChild(numCmdBuffersGroup.release());
2404 				}
2405 
2406 				groupingTypeGroup->addChild(descriptorTypeGroup.release());
2407 			}
2408 
2409 			pipelineTypeGroup->addChild(groupingTypeGroup.release());
2410 		}
2411 
2412 		dynamicOffsetTests->addChild(pipelineTypeGroup.release());
2413 	}
2414 
2415 	// Dynamic descriptor offset test for combined descriptor sets.
2416 	{
2417 		de::MovePtr<tcu::TestCaseGroup>	combinedDescriptorsTests(new tcu::TestCaseGroup(testCtx, "combined_descriptors", ""));
2418 
2419 		struct
2420 		{
2421 			const char* name;
2422 			const bool	reverseDescriptors;
2423 		}
2424 		const orders[] =
2425 		{
2426 			{	"same_order",		false	},
2427 			{	"reverse_order",	true	}
2428 		};
2429 
2430 		struct
2431 		{
2432 			const char* name;
2433 			const deUint32	offsetCount;
2434 			const deUint32	offsets[5];
2435 		}
2436 		const numOffsets[] =
2437 		{
2438 			{	"16",		16u,	{ 15u, 7u, 2u, 3u, 5u			}	},
2439 			{	"64",		64u,	{ 27u, 22u, 45u, 19u, 59u		}	},
2440 			{	"256",		256u,	{ 197u, 244u, 110u, 238u, 88u	}	}
2441 		};
2442 
2443 		struct
2444 		{
2445 			const char* name;
2446 			const bool	computeFirst;
2447 		}
2448 		const pipelineOrders[] =
2449 		{
2450 			{	"graphics_first",	false	},
2451 			{	"compute_first",	true	}
2452 		};
2453 
2454 		// Run tests for all offsets
2455 		{
2456 			de::MovePtr<tcu::TestCaseGroup>	allOffsetsGroup(new tcu::TestCaseGroup(testCtx, "all_offsets", ""));
2457 			de::MovePtr<tcu::TestCaseGroup>	singleOffsetGroup(new tcu::TestCaseGroup(testCtx, "single_offset", ""));
2458 
2459 			for (const auto& order : orders)
2460 			{
2461 				for (const auto& offsets : numOffsets)
2462 				{
2463 					for (const auto& pipeline : pipelineOrders)
2464 					{
2465 						allOffsetsGroup->addChild(new DynamicOffsetMixedTest(
2466 							testCtx,
2467 							std::string(order.name) + "_" + std::string(offsets.name) + "_" + pipeline.name,
2468 							"",
2469 							tcu::IVec2(32, 32),		// Render size
2470 							offsets.offsetCount,
2471 							true,					// All offsets
2472 							order.reverseDescriptors,
2473 							pipeline.computeFirst));
2474 						singleOffsetGroup->addChild(new DynamicOffsetMixedTest(
2475 							testCtx,
2476 							std::string(order.name) + "_" + std::string(offsets.name) + "_" + pipeline.name,
2477 							"",
2478 							tcu::IVec2(32, 32),		// Render size
2479 							offsets.offsetCount,
2480 							false,					// Single offset only
2481 							order.reverseDescriptors,
2482 							pipeline.computeFirst,
2483 							offsets.offsets[0],		// For vertex ubo
2484 							offsets.offsets[1],		// For shared ubo (fragment & compute)
2485 							offsets.offsets[2],		// For fragment ubo
2486 							offsets.offsets[3],		// For ssbo read only
2487 							offsets.offsets[4]));	// For ssbo write only
2488 					}
2489 				}
2490 			}
2491 			combinedDescriptorsTests->addChild(allOffsetsGroup.release());
2492 			combinedDescriptorsTests->addChild(singleOffsetGroup.release());
2493 		}
2494 
2495 		dynamicOffsetTests->addChild(combinedDescriptorsTests.release());
2496 	}
2497 
2498 	return dynamicOffsetTests.release();
2499 }
2500 
2501 } // pipeline
2502 } // vkt
2503