• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (C) 2022 Advanced Micro Devices, Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file vktBindingDescriptorBufferTests.cpp
22  * \brief Descriptor buffer (extension) tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "deSharedPtr.hpp"
26 #include "deUniquePtr.hpp"
27 #include "deRandom.hpp"
28 #include "tcuCommandLine.hpp"
29 #include "vktBindingDescriptorBufferTests.hpp"
30 #include "vktTestCaseUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32 #include "vktCustomInstancesDevices.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkObjUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkStrUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkImageUtil.hpp"
42 #include "vkRayTracingUtil.hpp"
43 
44 #include <algorithm>
45 
46 // The defines below can be changed for debugging purposes, otherwise keep them as is.
47 
48 #define DEBUG_FORCE_STAGED_UPLOAD			false	// false - prefer direct write to device-local memory
49 #define DEBUG_MIX_DIRECT_AND_STAGED_UPLOAD	true	// true  - use some staged uploads to test new access flag
50 
51 // Workaround a framework script bug.
52 #ifndef VK_PIPELINE_STAGE_2_TRANSFER_BIT
53 #define VK_PIPELINE_STAGE_2_TRANSFER_BIT VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR
54 #endif
55 
56 namespace vkt
57 {
58 namespace BindingModel
59 {
60 namespace
61 {
62 using namespace vk;
63 using de::MovePtr;
64 using de::UniquePtr;
65 using de::SharedPtr;
66 
67 constexpr deUint32 INDEX_INVALID	= ~0u;
68 constexpr deUint32 OFFSET_UNUSED	= ~0u;
69 constexpr deUint32 HASH_MASK_FOR_AS	= (1u << 19) - 1;
70 
71 constexpr deUint32	ConstResultBufferDwords		= 0x4;		// uvec4
72 constexpr deUint32	ConstInlineBlockDwords		= 0x40;		// 256 B spec minimum
73 constexpr deUint32	ConstUniformBufferDwords	= 0x1000;	// 16 KiB spec minimum
74 constexpr deUint32	ConstTexelBufferElements    = 512;
75 constexpr deUint32	ConstMaxDescriptorArraySize	= 3;		// at most define N-element descriptor arrays
76 constexpr deUint32  ConstRobustBufferAlignment  = 256;		// 256 is the worst-case alignment required by UBOs in robustness2
77 constexpr deUint32	ConstChecksPerBuffer		= 4;		// when verifying data in buffers, do at most N comparisons;
78 															// this is to avoid excessive shader execution time
79 
80 constexpr VkComponentMapping ComponentMappingIdentity =
81 {
82 	VK_COMPONENT_SWIZZLE_IDENTITY,
83 	VK_COMPONENT_SWIZZLE_IDENTITY,
84 	VK_COMPONENT_SWIZZLE_IDENTITY,
85 	VK_COMPONENT_SWIZZLE_IDENTITY,
86 };
87 
88 template<typename T>
u32(const T & value)89 inline deUint32 u32(const T& value)
90 {
91 	return static_cast<deUint32>(value);
92 }
93 
94 template <typename T, typename... args_t>
newMovePtr(args_t &&...args)95 inline de::MovePtr<T> newMovePtr(args_t&&... args)
96 {
97 	return de::MovePtr<T>(new T(::std::forward<args_t>(args)...));
98 }
99 
100 template <typename T>
reset(Move<T> & ptr)101 inline void reset(Move<T>& ptr)
102 {
103 	ptr = Move<T>();
104 }
105 
106 template <typename T>
reset(MovePtr<T> & ptr)107 inline void reset(MovePtr<T>& ptr)
108 {
109 	ptr.clear();
110 }
111 
112 template<typename T>
makeSharedUniquePtr()113 inline SharedPtr<UniquePtr<T> > makeSharedUniquePtr()
114 {
115 	return SharedPtr<UniquePtr<T> >(
116 		new UniquePtr<T>(
117 			new T()));
118 }
119 
offsetPtr(void * ptr,VkDeviceSize offset)120 inline void* offsetPtr(void* ptr, VkDeviceSize offset)
121 {
122 	return reinterpret_cast<char*>(ptr) + offset;
123 }
124 
offsetPtr(const void * ptr,VkDeviceSize offset)125 inline const void* offsetPtr(const void* ptr, VkDeviceSize offset)
126 {
127 	return reinterpret_cast<const char*>(ptr) + offset;
128 }
129 
130 // Calculate the byte offset of ptr from basePtr.
131 // This can be useful if an object at ptr is suballocated from a larger allocation at basePtr, for example.
basePtrOffsetOf(const void * basePtr,const void * ptr)132 inline std::size_t basePtrOffsetOf(const void* basePtr, const void* ptr)
133 {
134 	DE_ASSERT(basePtr <= ptr);
135 	return static_cast<std::size_t>(static_cast<const deUint8*>(ptr) - static_cast<const deUint8*>(basePtr));
136 }
137 
getShaderGroupHandleSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)138 deUint32 getShaderGroupHandleSize (const InstanceInterface& vki,
139 	const VkPhysicalDevice	physicalDevice)
140 {
141 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
142 
143 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
144 
145 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
146 }
147 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)148 deUint32 getShaderGroupBaseAlignment (const InstanceInterface& vki,
149 	const VkPhysicalDevice	physicalDevice)
150 {
151 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
152 
153 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
154 
155 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
156 }
157 
getVkBuffer(const de::MovePtr<BufferWithMemory> & buffer)158 VkBuffer getVkBuffer (const de::MovePtr<BufferWithMemory>& buffer)
159 {
160 	VkBuffer result = (buffer.get() == DE_NULL) ? DE_NULL : buffer->get();
161 
162 	return result;
163 }
164 
makeStridedDeviceAddressRegion(const DeviceInterface & vkd,const VkDevice device,VkBuffer buffer,VkDeviceSize size)165 VkStridedDeviceAddressRegionKHR makeStridedDeviceAddressRegion (const DeviceInterface& vkd, const VkDevice device, VkBuffer buffer, VkDeviceSize size)
166 {
167 	const VkDeviceSize sizeFixed = ((buffer == DE_NULL) ? 0ull : size);
168 
169 	return makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, buffer, 0), sizeFixed, sizeFixed);
170 }
171 
getAccelerationStructureDeviceAddress(DeviceDriver & deviceDriver,VkDevice device,VkAccelerationStructureKHR accelerationStructure)172 VkDeviceAddress getAccelerationStructureDeviceAddress (DeviceDriver&				deviceDriver,
173 													   VkDevice						device,
174 													   VkAccelerationStructureKHR	accelerationStructure)
175 {
176 	const VkAccelerationStructureDeviceAddressInfoKHR	addressInfo =
177 	{
178 		VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR,	// VkStructureType				sType
179 		DE_NULL,															// const void*					pNext
180 		accelerationStructure												// VkAccelerationStructureKHR	accelerationStructure
181 	};
182 	const VkDeviceAddress								deviceAddress = deviceDriver.getAccelerationStructureDeviceAddressKHR(device, &addressInfo);
183 
184 	DE_ASSERT(deviceAddress != DE_NULL);
185 
186 	return deviceAddress;
187 }
188 
189 // Used to distinguish different test implementations.
190 enum class TestVariant : deUint32
191 {
192 	SINGLE,								// basic sanity check for descriptor/shader combinations
193 	MULTIPLE,							// multiple buffer bindings with various descriptor types
194 	MAX,								// verify max(Sampler/Resource)DescriptorBufferBindings
195 	EMBEDDED_IMMUTABLE_SAMPLERS,		// various usages of embedded immutable samplers
196 	PUSH_DESCRIPTOR,					// use push descriptors and descriptor buffer at the same time
197 	PUSH_TEMPLATE,						// use push descriptor template and descriptor buffer at the same time
198 	ROBUST_BUFFER_ACCESS,				// robust buffer access
199 	ROBUST_NULL_DESCRIPTOR,				// robustness2 with null descriptor
200 	CAPTURE_REPLAY,						// capture and replay capability with descriptor buffers
201 };
202 
203 // Optional; Used to add variations for a specific test case.
204 enum class SubCase : deUint32
205 {
206 	NONE,								// no sub case, i.e. a baseline test case
207 	IMMUTABLE_SAMPLERS,					// treat all samplers as immutable
208 	CAPTURE_REPLAY_CUSTOM_BORDER_COLOR,	// in capture/replay tests, test VK_EXT_custom_border_color interaction
209 	SINGLE_BUFFER,						// use push descriptors and descriptor buffer at the same time using single buffer
210 };
211 
212 // A simplified descriptor binding, used to define the test case behavior at a high level.
213 struct SimpleBinding
214 {
215 	deUint32			set;
216 	deUint32			binding;
217 	VkDescriptorType	type;
218 	deUint32			count;
219 	deUint32			inputAttachmentIndex;
220 
221 	bool				isResultBuffer;				// binding used for compute buffer results
222 	bool				isEmbeddedImmutableSampler;	// binding used as immutable embedded sampler
223 	bool				isRayTracingAS;				// binding used for raytracing acceleration structure
224 };
225 
226 // Scan simple bindings for the binding with the compute and ray tracing shader's result storage buffer.
getResultBufferIndex(const std::vector<SimpleBinding> & simpleBindings)227 deUint32 getResultBufferIndex(const std::vector<SimpleBinding>& simpleBindings)
228 {
229 	bool	 found						= false;
230 	deUint32 resultBufferIndex	= 0;
231 
232 	for (const auto& sb : simpleBindings)
233 	{
234 		if (sb.isResultBuffer)
235 		{
236 			found = true;
237 
238 			break;
239 		}
240 
241 		++resultBufferIndex;
242 	}
243 
244 	if (!found)
245 	{
246 		resultBufferIndex = INDEX_INVALID;
247 	}
248 
249 	return resultBufferIndex;
250 }
251 
252 
253 // Scan simple bindings for the binding with the ray tracing acceleration structure
getRayTracingASIndex(const std::vector<SimpleBinding> & simpleBindings)254 deUint32 getRayTracingASIndex(const std::vector<SimpleBinding>& simpleBindings)
255 {
256 	deUint32 ndx	= 0;
257 	deUint32 result	= INDEX_INVALID;
258 
259 	for (const auto& sb : simpleBindings)
260 	{
261 		if (sb.isRayTracingAS)
262 		{
263 			result = ndx;
264 
265 			break;
266 		}
267 
268 		++ndx;
269 	}
270 
271 	DE_ASSERT(result != INDEX_INVALID);
272 
273 	return result;
274 }
275 
276 // The parameters for a test case (with the exclusion of simple bindings).
277 // Not all values are used by every test variant.
278 struct TestParams
279 {
280 	deUint32					hash;				// a value used to "salt" results in memory to get unique values per test case
281 	TestVariant					variant;			// general type of the test case
282 	SubCase						subcase;			// a variation of the specific test case
283 	VkShaderStageFlagBits		stage;				// which shader makes use of the bindings
284 	VkQueueFlagBits				queue;				// which queue to use for the access
285 	deUint32					bufferBindingCount;	// number of buffer bindings to create
286 	deUint32					setsPerBuffer;		// how may sets to put in one buffer binding
287 
288 	// Basic, null descriptor, or capture/replay test
289 	VkDescriptorType			descriptor;			// descriptor type under test
290 
291 	// Max bindings test and to check the supported limits in other cases
292 	deUint32					samplerBufferBindingCount;
293 	deUint32					resourceBufferBindingCount;
294 
295 	// Max embedded immutable samplers test
296 	deUint32					embeddedImmutableSamplerBufferBindingCount;
297 	deUint32					embeddedImmutableSamplersPerBuffer;
298 
299 	// Push descriptors
300 	deUint32					pushDescriptorSetIndex;		// which descriptor set is updated with push descriptor/template
301 
isComputevkt::BindingModel::__anon26c3a83a0111::TestParams302 	bool isCompute() const
303 	{
304 		return stage == VK_SHADER_STAGE_COMPUTE_BIT;
305 	}
306 
isGraphicsvkt::BindingModel::__anon26c3a83a0111::TestParams307 	bool isGraphics() const
308 	{
309 		return (stage & VK_SHADER_STAGE_ALL_GRAPHICS) != 0;
310 	}
311 
isGeometryvkt::BindingModel::__anon26c3a83a0111::TestParams312 	bool isGeometry() const
313 	{
314 		return stage == VK_SHADER_STAGE_GEOMETRY_BIT;
315 	}
316 
isTessellationvkt::BindingModel::__anon26c3a83a0111::TestParams317 	bool isTessellation() const
318 	{
319 		return (stage & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) != 0;
320 	}
321 
isPushDescriptorTestvkt::BindingModel::__anon26c3a83a0111::TestParams322 	bool isPushDescriptorTest() const
323 	{
324 		return (variant == TestVariant::PUSH_DESCRIPTOR) || (variant == TestVariant::PUSH_TEMPLATE);
325 	}
326 
isAccelerationStructurevkt::BindingModel::__anon26c3a83a0111::TestParams327 	bool isAccelerationStructure() const
328 	{
329 		return descriptor == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
330 	}
331 
isRayTracingvkt::BindingModel::__anon26c3a83a0111::TestParams332 	bool isRayTracing() const
333 	{
334 		return isAllRayTracingStages(stage);
335 	}
336 
337 	// The resource accessed via this descriptor type has capture/replay enabled.
isCaptureReplayDescriptorvkt::BindingModel::__anon26c3a83a0111::TestParams338 	bool isCaptureReplayDescriptor(VkDescriptorType otherType) const
339 	{
340 		return (variant == TestVariant::CAPTURE_REPLAY) && (descriptor == otherType);
341 	}
342 
isAccelerationStructureOptionalvkt::BindingModel::__anon26c3a83a0111::TestParams343 	bool isAccelerationStructureOptional () const
344 	{
345 		switch (variant)
346 		{
347 			case TestVariant::MULTIPLE:
348 			case TestVariant::PUSH_DESCRIPTOR:
349 			case TestVariant::PUSH_TEMPLATE:
350 				return true;
351 			default:
352 				return false;
353 		}
354 	}
355 
isAccelerationStructureObligatoryvkt::BindingModel::__anon26c3a83a0111::TestParams356 	bool isAccelerationStructureObligatory () const
357 	{
358 		switch (variant)
359 		{
360 			case TestVariant::SINGLE:
361 			case TestVariant::ROBUST_NULL_DESCRIPTOR:
362 			case TestVariant::CAPTURE_REPLAY:
363 				return isAccelerationStructure();
364 			default:
365 				return false;
366 		}
367 	}
368 
369 	// Update the hash field. Must be called after changing the value of any other parameters.
updateHashvkt::BindingModel::__anon26c3a83a0111::TestParams370 	void updateHash(uint32_t basehash)
371 	{
372 		hash = deUint32Hash(basehash);
373 
374 		hash = isAccelerationStructure() ? (basehash & HASH_MASK_FOR_AS) : basehash;
375 	}
376 };
377 
378 // A convenience holder for a buffer-related data.
379 struct BufferAlloc
380 {
381 	VkDeviceSize			size					= 0;
382 	VkDeviceAddress			deviceAddress			= 0;	// non-zero if used
383 	VkBufferUsageFlags		usage					= 0;
384 	uint64_t				opaqueCaptureAddress	= 0;
385 
386 	Move<VkBuffer>			buffer;
387 	MovePtr<Allocation>		alloc;
388 
389 	BufferAlloc() = default;
390 	BufferAlloc(BufferAlloc&) = delete;
391 
loadDeviceAddressvkt::BindingModel::__anon26c3a83a0111::BufferAlloc392 	void loadDeviceAddress(const DeviceInterface& vk, VkDevice device)
393 	{
394 		VkBufferDeviceAddressInfo bdaInfo = initVulkanStructure();
395 		bdaInfo.buffer = *buffer;
396 
397 		deviceAddress = vk.getBufferDeviceAddress(device, &bdaInfo);
398 	}
399 };
400 
401 using BufferAllocPtr = SharedPtr<BufferAlloc>;
402 
403 // A convenience holder for image-related data.
404 struct ImageAlloc
405 {
406 	VkImageCreateInfo		info					= {};
407 	VkDeviceSize			sizeBytes				= 0;
408 	VkImageLayout			layout					= VK_IMAGE_LAYOUT_UNDEFINED;	// layout used when image is accessed
409 	uint64_t				opaqueCaptureAddress	= 0;
410 
411 	Move<VkImage>			image;
412 	Move<VkImageView>		imageView;
413 	MovePtr<Allocation>		alloc;
414 
415 	ImageAlloc() = default;
416 	ImageAlloc(ImageAlloc&) = delete;
417 };
418 
419 using ImageAllocPtr = SharedPtr<ImageAlloc>;
420 
421 // A descriptor binding with supporting data.
422 class Binding
423 {
424 public:
425     uint32_t				binding;
426     VkDescriptorType		descriptorType;
427     uint32_t				descriptorCount;
428 	VkShaderStageFlags		stageFlags;
429 
430 	VkDeviceSize			offset;
431 	deUint32				inputAttachmentIndex;	// if used
432 	bool					isResultBuffer;			// used with compute shaders
433 	bool					isRayTracingAS;			// used with raytracing shaders
434 
isTestableDescriptor() const435 	bool					isTestableDescriptor() const
436 	{
437 		return !isRayTracingAS && !isResultBuffer;
438 	}
439 
440 	// Index into the vector of resources in the main test class, if used.
441 	// It's an array, because a binding may have several arrayed descriptors.
442 	deUint32				perBindingResourceIndex[ConstMaxDescriptorArraySize];
443 
444 	// An array of immutable samplers, if used by the binding.
445 	VkSampler				immutableSamplers[ConstMaxDescriptorArraySize];
446 
Binding()447 	Binding()
448 		: binding(0)
449 		, descriptorType(VK_DESCRIPTOR_TYPE_SAMPLER)
450 		, descriptorCount(0)
451 		, stageFlags(0)
452 		, offset(0)
453 		, inputAttachmentIndex(0)
454 		, isResultBuffer(false)
455 		, isRayTracingAS(false)
456 	{
457 		for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(perBindingResourceIndex); ++i)
458 		{
459 			perBindingResourceIndex[i]	= INDEX_INVALID;
460 			immutableSamplers[i]		= 0;
461 		}
462 	}
463 };
464 
465 // Get an array of descriptor bindings, this is used in descriptor set layout creation.
getDescriptorSetLayoutBindings(const std::vector<Binding> & allBindings)466 std::vector<VkDescriptorSetLayoutBinding> getDescriptorSetLayoutBindings(const std::vector<Binding>& allBindings)
467 {
468 	std::vector<VkDescriptorSetLayoutBinding> result;
469 	result.reserve(allBindings.size());
470 
471 	for (auto& binding : allBindings)
472 	{
473 		VkDescriptorSetLayoutBinding dslBinding {};
474 		dslBinding.binding				= binding.binding;
475 		dslBinding.descriptorType		= binding.descriptorType;
476 		dslBinding.descriptorCount		= binding.descriptorCount;
477 		dslBinding.stageFlags			= binding.stageFlags;
478 
479 		if (binding.immutableSamplers[0] != DE_NULL)
480 		{
481 			dslBinding.pImmutableSamplers = binding.immutableSamplers;
482 		}
483 
484 		result.emplace_back(dslBinding);
485 	}
486 
487 	return result;
488 }
489 
490 // Descriptor data used with push descriptors (regular and templates).
491 struct PushDescriptorData
492 {
493 	VkDescriptorImageInfo		imageInfos[ConstMaxDescriptorArraySize];
494 	VkDescriptorBufferInfo		bufferInfos[ConstMaxDescriptorArraySize];
495 	VkBufferView				texelBufferViews[ConstMaxDescriptorArraySize];
496 	VkAccelerationStructureKHR	accelerationStructures[ConstMaxDescriptorArraySize];
497 };
498 
499 // A convenience holder for a descriptor set layout and its bindings.
500 struct DescriptorSetLayoutHolder
501 {
502 	std::vector<Binding>			bindings;
503 
504 	Move<VkDescriptorSetLayout>		layout;
505 	VkDeviceSize					sizeOfLayout					= 0;
506 	deUint32						bufferIndex						= INDEX_INVALID;
507 	VkDeviceSize					bufferOffset					= 0;
508 	VkDeviceSize					stagingBufferOffset				= OFFSET_UNUSED;
509 	bool							hasEmbeddedImmutableSamplers	= false;
510 	bool							usePushDescriptors				= false;	// instead of descriptor buffer
511 
512 	DescriptorSetLayoutHolder() = default;
513 	DescriptorSetLayoutHolder(DescriptorSetLayoutHolder&) = delete;
514 };
515 
516 using DSLPtr = SharedPtr<UniquePtr<DescriptorSetLayoutHolder> >;
517 
518 // Get an array of descriptor set layouts.
getDescriptorSetLayouts(const std::vector<DSLPtr> & dslPtrs)519 std::vector<VkDescriptorSetLayout> getDescriptorSetLayouts(const std::vector<DSLPtr>& dslPtrs)
520 {
521 	std::vector<VkDescriptorSetLayout> result;
522 	result.reserve(dslPtrs.size());
523 
524 	for (auto& pDsl : dslPtrs)
525 	{
526 		result.emplace_back((**pDsl).layout.get());
527 	}
528 
529 	return result;
530 }
531 
532 // A helper struct to keep descriptor's underlying resource data.
533 // This is intended to be flexible and support a mix of buffer/image/sampler, depending on the binding type.
534 struct ResourceHolder
535 {
536 	BufferAlloc									buffer;
537 	ImageAlloc									image;
538 	Move<VkSampler>								sampler;
539 	Move<VkSamplerYcbcrConversion>				samplerYcbcrConversion;
540 	Move<VkBufferView>							bufferView;
541 	SharedPtr<BottomLevelAccelerationStructure>	rtBlas;
542 	MovePtr<TopLevelAccelerationStructure>		rtTlas;
543 
544 	struct
545 	{
546 		std::vector<deUint8>	bufferData;
547 		std::vector<deUint8>	imageData;
548 		std::vector<deUint8>	imageViewData;
549 		std::vector<deUint8>	samplerData;
550 		std::vector<deUint8>	accelerationStructureDataBlas;
551 		std::vector<deUint8>	accelerationStructureDataTlas;
552 	} captureReplay;
553 
554 	ResourceHolder() = default;
555 	ResourceHolder(ResourceHolder&) = delete;
556 };
557 
558 using ResourcePtr = SharedPtr<UniquePtr<ResourceHolder> >;
559 
560 // Used in test case name generation.
toString(VkQueueFlagBits queue)561 std::string toString (VkQueueFlagBits queue)
562 {
563 	switch (queue)
564 	{
565 	case VK_QUEUE_GRAPHICS_BIT:		return "graphics";
566 	case VK_QUEUE_COMPUTE_BIT:		return "compute";
567 
568 	default:
569 		DE_ASSERT(false);
570 		break;
571 	}
572 	return "";
573 }
574 
575 // Used in test case name generation.
toString(VkDescriptorType type)576 std::string toString (VkDescriptorType type)
577 {
578 	switch (type)
579 	{
580 	case VK_DESCRIPTOR_TYPE_SAMPLER:					return "sampler";
581 	case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:		return "combined_image_sampler";
582 	case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:				return "sampled_image";
583 	case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:				return "storage_image";
584 	case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:		return "uniform_texel_buffer";
585 	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:		return "storage_texel_buffer";
586 	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:				return "uniform_buffer";
587 	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:				return "storage_buffer";
588 	case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:			return "input_attachment";
589 	case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:		return "inline_uniform_block";
590 	case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: return "acceleration_structure";
591 
592 	default:
593 		DE_ASSERT(false);
594 		break;
595 	}
596 	return "";
597 }
598 
599 // Used in test case name generation.
toString(VkShaderStageFlagBits stage)600 std::string toString (VkShaderStageFlagBits stage)
601 {
602 	switch (stage)
603 	{
604 		case VK_SHADER_STAGE_VERTEX_BIT:					return "vert";
605 		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:		return "tesc";
606 		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:	return "tese";
607 		case VK_SHADER_STAGE_GEOMETRY_BIT:					return "geom";
608 		case VK_SHADER_STAGE_FRAGMENT_BIT:					return "frag";
609 		case VK_SHADER_STAGE_COMPUTE_BIT:					return "comp";
610 		case VK_SHADER_STAGE_RAYGEN_BIT_KHR:				return "rgen";
611 		case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:				return "ahit";
612 		case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:			return "chit";
613 		case VK_SHADER_STAGE_MISS_BIT_KHR:					return "miss";
614 		case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:			return "sect";
615 		case VK_SHADER_STAGE_CALLABLE_BIT_KHR:				return "call";
616 
617 		default:
618 			DE_ASSERT(false);
619 			break;
620 	}
621 
622 	return "";
623 }
624 
625 // Used in test case name generation.
getCaseNameUpdateHash(TestParams & params,uint32_t baseHash)626 std::string getCaseNameUpdateHash(TestParams& params, uint32_t baseHash)
627 {
628 	std::ostringstream str;
629 
630 	str << toString(params.queue)
631 		<< "_"
632 		<< toString(params.stage);
633 
634 	if ((params.variant == TestVariant::SINGLE) ||
635 		(params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR) ||
636 		(params.variant == TestVariant::CAPTURE_REPLAY))
637 	{
638 		str << "_" << toString(params.descriptor);
639 
640 		if (params.subcase == SubCase::CAPTURE_REPLAY_CUSTOM_BORDER_COLOR)
641 		{
642 			str << "_custom_border_color";
643 		}
644 	}
645 	else if (params.variant == TestVariant::MULTIPLE)
646 	{
647 		str << "_buffers" << params.bufferBindingCount
648 			<< "_sets" << params.setsPerBuffer;
649 	}
650 	else if (params.variant == TestVariant::MAX)
651 	{
652 		str << "_sampler" << params.samplerBufferBindingCount
653 			<< "_resource" << params.resourceBufferBindingCount;
654 	}
655 	else if (params.variant == TestVariant::EMBEDDED_IMMUTABLE_SAMPLERS)
656 	{
657 		str << "_buffers" << params.embeddedImmutableSamplerBufferBindingCount
658 			<< "_samplers" << params.embeddedImmutableSamplersPerBuffer;
659 	}
660 	else if (params.isPushDescriptorTest())
661 	{
662 		str << "_sets" << (params.bufferBindingCount + 1)
663 			<< "_push_set" << params.pushDescriptorSetIndex
664 			<< ((params.subcase == SubCase::SINGLE_BUFFER) ? "_single_buffer" : "");
665 	}
666 
667 	if (params.subcase == SubCase::IMMUTABLE_SAMPLERS)
668 	{
669 		str << "_imm_samplers";
670 	}
671 
672 	params.updateHash(baseHash ^ deStringHash(str.str().c_str()));
673 
674 	return str.str();
675 }
676 
677 // Used by shaders to identify a specific binding.
packBindingArgs(deUint32 set,deUint32 binding,deUint32 arrayIndex)678 deUint32 packBindingArgs(deUint32 set, deUint32 binding, deUint32 arrayIndex)
679 {
680 	DE_ASSERT(set		 < 0x40);
681 	DE_ASSERT(binding	 < 0x40);
682 	DE_ASSERT(arrayIndex < 0x80);
683 
684 	return (arrayIndex << 12) | ((set & 0x3Fu) << 6) | (binding & 0x3Fu);
685 }
686 
687 // Used by shaders to identify a specific binding.
unpackBindingArgs(deUint32 packed,deUint32 * pOutSet,deUint32 * pBinding,deUint32 * pArrayIndex)688 void unpackBindingArgs(deUint32 packed, deUint32* pOutSet, deUint32* pBinding, deUint32* pArrayIndex)
689 {
690 	if (pBinding != nullptr)
691 	{
692 		*pBinding = packed & 0x3Fu;
693 	}
694 	if (pOutSet != nullptr)
695 	{
696 		*pOutSet = (packed >> 6) & 0x3Fu;
697 	}
698 	if (pArrayIndex != nullptr)
699 	{
700 		*pArrayIndex = (packed >> 12) & 0x7Fu;
701 	}
702 }
703 
704 // The expected data read through a descriptor. Try to get a unique value per test and binding.
getExpectedData(deUint32 hash,deUint32 set,deUint32 binding,deUint32 arrayIndex=0)705 deUint32 getExpectedData(deUint32 hash, deUint32 set, deUint32 binding, deUint32 arrayIndex = 0)
706 {
707 	return hash ^ packBindingArgs(set, binding, arrayIndex);
708 }
709 
710 // Used by shaders.
glslFormat(deUint32 value)711 std::string glslFormat(deUint32 value)
712 {
713 	return std::to_string(value) + "u";
714 }
715 
716 // Generate a unique shader resource name for a binding.
glslResourceName(deUint32 set,deUint32 binding)717 std::string glslResourceName(deUint32 set, deUint32 binding)
718 {
719 	// A generic name for any accessible shader binding.
720 	std::ostringstream str;
721 	str << "res_" << set << "_" << binding;
722 	return str.str();
723 }
724 
725 // Generate GLSL that declares a descriptor binding.
glslDeclareBinding(VkDescriptorType type,deUint32 set,deUint32 binding,deUint32 count,deUint32 attachmentIndex,deUint32 bufferArraySize)726 std::string glslDeclareBinding(
727 	VkDescriptorType	type,
728 	deUint32			set,
729 	deUint32			binding,
730 	deUint32			count,
731 	deUint32			attachmentIndex,
732 	deUint32			bufferArraySize)
733 {
734 	std::ostringstream str;
735 
736 	str << "layout(set = " << set << ", binding = " << binding;
737 
738 	// Additional layout information
739 	switch (type)
740 	{
741 	case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
742 	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
743 		str << ", r32ui) ";
744 		break;
745 	case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
746 		str << ", input_attachment_index = " << attachmentIndex << ") ";
747 		break;
748 	default:
749 		str << ") ";
750 		break;
751 	}
752 
753 	switch (type)
754 	{
755 	case VK_DESCRIPTOR_TYPE_SAMPLER:
756 		str << "uniform sampler ";
757 		break;
758 	case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
759 		str << "uniform usampler2D ";
760 		break;
761 	case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
762 		str << "uniform utexture2D ";
763 		break;
764 	case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
765 		str << "uniform uimage2D ";
766 		break;
767 	case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
768 		str << "uniform utextureBuffer ";
769 		break;
770 	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
771 		str << "uniform uimageBuffer ";
772 		break;
773 	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
774 	case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
775 		DE_ASSERT(bufferArraySize != 0);
776 		DE_ASSERT((bufferArraySize % 4) == 0);
777 		// std140 layout rules, each array element is aligned to 16 bytes.
778 		// Due to this, we will use uvec4 instead to access all dwords.
779 		str << "uniform Buffer_" << set << "_" << binding << " {\n"
780 			<< "    uvec4 data[" << (bufferArraySize / 4) << "];\n"
781 			<< "} ";
782 		break;
783 	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
784 		DE_ASSERT(bufferArraySize != 0);
785 		str << "buffer Buffer_" << set << "_" << binding << " {\n"
786 			<< "    uint data[" << bufferArraySize << "];\n"
787 			<< "} ";
788 		break;
789 	case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
790 		str << "uniform usubpassInput ";
791 		break;
792 	case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
793 		str << "uniform accelerationStructureEXT ";
794 		break;
795 	default:
796 		DE_ASSERT(0);
797 		break;
798 	}
799 
800 	str << glslResourceName(set, binding);
801 
802 	if (count > 1)
803 	{
804 		str << "[" << count << "];\n";
805 	}
806 	else
807 	{
808 		str << ";\n";
809 	}
810 
811 	return str.str();
812 }
813 
814 // Generate all GLSL descriptor set/binding declarations.
glslGlobalDeclarations(const TestParams & params,const std::vector<SimpleBinding> & simpleBindings,bool accStruct)815 std::string glslGlobalDeclarations(const TestParams& params, const std::vector<SimpleBinding>& simpleBindings, bool accStruct)
816 {
817 	DE_UNREF(params);
818 
819 	std::ostringstream str;
820 
821 	if (accStruct)
822 		str << "#extension GL_EXT_ray_query : require\n";
823 
824 	for (const auto& sb : simpleBindings)
825 	{
826 		const deUint32 arraySize =
827 			sb.isResultBuffer ? ConstResultBufferDwords :
828 			(sb.type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) ? ConstInlineBlockDwords : ConstUniformBufferDwords;
829 
830 		str << glslDeclareBinding(sb.type, sb.set, sb.binding, sb.count, sb.inputAttachmentIndex, arraySize);
831 	}
832 
833 	if (accStruct)
834 	{
835 		str << ""
836 			"uint queryAS(accelerationStructureEXT rayQueryTopLevelAccelerationStructure)\n"
837 			"{\n"
838 			"	const uint  rayFlags = gl_RayFlagsNoOpaqueEXT;\n"
839 			"	const uint  cullMask = 0xFF;\n"
840 			"	const float tmin     = 0.0f;\n"
841 			"	const float tmax     = 524288.0f; // 2^^19\n"
842 			"	const vec3  origin   = vec3(0.0f, 0.0f, 0.0f);\n"
843 			"	const vec3  direct   = vec3(0.0f, 0.0f, 1.0f);\n"
844 			"	rayQueryEXT rayQuery;\n"
845 			"\n"
846 			"	rayQueryInitializeEXT(rayQuery, rayQueryTopLevelAccelerationStructure, rayFlags, cullMask, origin, tmin, direct, tmax);\n"
847 			"\n"
848 			"	if (rayQueryProceedEXT(rayQuery))\n"
849 			"	{\n"
850 			"		if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCandidateIntersectionTriangleEXT)\n"
851 			"		{\n"
852 			"			return uint(rayQueryGetIntersectionTEXT(rayQuery, false));\n"
853 			"		}\n"
854 			"	}\n"
855 			"\n"
856 			"	return 0u;\n"
857 			"}\n"
858 			"\n";
859 	}
860 
861 	return str.str();
862 }
863 
864 // This function is used to return additional diagnostic information for a failed descriptor binding.
865 // For example, result Y is the packed binding information and result Z is the array index (for arrayed descriptors, or buffers).
glslResultBlock(const std::string & indent,const std::string & resultY,const std::string & resultZ="")866 std::string glslResultBlock(const std::string& indent, const std::string& resultY, const std::string& resultZ = "")
867 {
868 	std::ostringstream str;
869 	str << "{\n"
870 		<< indent << "	result.x += 1;\n"
871 		<< indent << "} else if (result.y == 0) {\n"
872 		<< indent << "	result.y = " << resultY << ";\n";
873 
874 	if (!resultZ.empty())
875 	{
876 		str << indent << "	result.z = " << resultZ << ";\n";
877 	}
878 
879 	str << indent << "}\n";
880 	return str.str();
881 }
882 
883 // Get the number of iterations required to access all elements of a buffer.
884 // This mainly exists because we access UBOs as uvec4.
getBufferLoopIterations(VkDescriptorType type)885 inline deUint32 getBufferLoopIterations(VkDescriptorType type)
886 {
887 	switch (type)
888 	{
889 	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
890 		return ConstUniformBufferDwords / 4;
891 
892 	case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
893 		return ConstInlineBlockDwords / 4;
894 
895 	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
896 		return ConstUniformBufferDwords;
897 
898 	case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
899 	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
900 		return ConstTexelBufferElements;
901 
902 	default:
903 		// Ignored
904 		return 0;
905 	}
906 }
907 
908 // Generate GLSL that reads through the binding and compares the value.
909 // Successful reads increment a counter, while failed read will write back debug information.
glslOutputVerification(const TestParams & params,const std::vector<SimpleBinding> & simpleBindings,bool)910 std::string glslOutputVerification(const TestParams& params, const std::vector<SimpleBinding>& simpleBindings, bool)
911 {
912 	std::ostringstream str;
913 
914 	if ((params.variant == TestVariant::SINGLE) ||
915 		(params.variant == TestVariant::MULTIPLE) ||
916 		(params.variant == TestVariant::PUSH_DESCRIPTOR) ||
917 		(params.variant == TestVariant::PUSH_TEMPLATE) ||
918 		(params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR) ||
919 		(params.variant == TestVariant::CAPTURE_REPLAY))
920 	{
921 		// Read at least one value from a descriptor and compare it.
922 		// For buffers, verify every element.
923 		//
924 		// With null descriptors, reads must always return zero.
925 
926 		for (const auto& sb : simpleBindings)
927 		{
928 			deUint32 samplerIndex = INDEX_INVALID;
929 
930 			if (sb.isResultBuffer || sb.isRayTracingAS)
931 			{
932 				// Used by other bindings.
933 				continue;
934 			}
935 
936 			if (sb.type == VK_DESCRIPTOR_TYPE_SAMPLER)
937 			{
938 				// Used by sampled images.
939 				continue;
940 			}
941 			else if (sb.type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
942 			{
943 				// Sampled images require a sampler to use.
944 				// Find a suitable sampler within the same descriptor set.
945 
946 				bool found = false;
947 				samplerIndex = 0;
948 
949 				for (const auto& sb1 : simpleBindings)
950 				{
951 					if ((sb.set == sb1.set) && (sb1.type == VK_DESCRIPTOR_TYPE_SAMPLER))
952 					{
953 						found = true;
954 						break;
955 					}
956 
957 					++samplerIndex;
958 				}
959 
960 				if (!found)
961 				{
962 					samplerIndex = INDEX_INVALID;
963 				}
964 			}
965 
966 			const deUint32 bufferLoopIterations	= getBufferLoopIterations(sb.type);
967 			const deUint32 loopIncrement		= bufferLoopIterations / (ConstChecksPerBuffer - 1);
968 
969 			// Ensure we won't miss the last check (the index will always be less than the buffer length).
970 			DE_ASSERT((bufferLoopIterations == 0) || ((bufferLoopIterations % (ConstChecksPerBuffer - 1)) != 0));
971 
972 			const bool isNullDescriptor		= (params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR) && (sb.type == params.descriptor);
973 			const bool isCustomBorderColor  = (params.subcase == SubCase::CAPTURE_REPLAY_CUSTOM_BORDER_COLOR);
974 
975 			for (deUint32 arrayIndex = 0; arrayIndex < sb.count; ++arrayIndex)
976 			{
977 				// Input attachment index increases with array index.
978 				const auto expectedData		   = glslFormat(isNullDescriptor ? 0 : getExpectedData(params.hash, sb.set, sb.binding, sb.inputAttachmentIndex + arrayIndex));
979 				const auto expectedBorderColor = isNullDescriptor ? "uvec4(0)" : isCustomBorderColor ? "uvec4(2, 0, 0, 1)" : "uvec4(0, 0, 0, 1)";
980 				const auto bindingArgs		   = glslFormat(packBindingArgs(sb.set, sb.binding, sb.inputAttachmentIndex + arrayIndex));
981 				const auto& subscript		   = (sb.count > 1) ? "[" + std::to_string(arrayIndex) + "]" : "";
982 
983 				if (sb.type == VK_DESCRIPTOR_TYPE_SAMPLER)
984 				{
985 					TCU_THROW(InternalError, "Sampler is tested implicitly");
986 				}
987 				else if (sb.type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
988 				{
989 					str << "    if (queryAS(" << glslResourceName(sb.set, sb.binding) << subscript << ") == " << expectedData << ") " << glslResultBlock("\t", bindingArgs);
990 				}
991 				else if (sb.type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
992 				{
993 					str << "	if (subpassLoad(" << glslResourceName(sb.set, sb.binding) << subscript << ").r == " << expectedData << ") " << glslResultBlock("\t", bindingArgs);
994 				}
995 				else if (sb.type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
996 				{
997 					DE_ASSERT(samplerIndex != INDEX_INVALID);
998 					const auto& samplerSb		 = simpleBindings[samplerIndex];
999 					const auto& samplerSubscript = (samplerSb.count > 1) ? "[" + std::to_string(arrayIndex % samplerSb.count) + "]" : "";
1000 
1001 					// With samplers, verify the image color and the border color.
1002 
1003 					std::stringstream samplerStr;
1004 					samplerStr << "usampler2D("
1005 							   << glslResourceName(sb.set, sb.binding)				 << subscript << ", "
1006 							   << glslResourceName(samplerSb.set, samplerSb.binding) << samplerSubscript << ")";
1007 
1008 					str << "	if ((textureLod(" << samplerStr.str() << ", vec2(0, 0), 0).r == " << expectedData << ") &&\n"
1009 						<< "	    (textureLod(" << samplerStr.str() << ", vec2(-1, 0), 0) == " << expectedBorderColor << ")) "
1010 						<< glslResultBlock("\t", bindingArgs);
1011 				}
1012 				else if (sb.type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1013 				{
1014 					str << "	if ((textureLod(" << glslResourceName(sb.set, sb.binding) << subscript << ", vec2(0, 0), 0).r == " << expectedData << ") &&\n"
1015 						<< "	    (textureLod(" << glslResourceName(sb.set, sb.binding) << subscript << ", vec2(-1, 0), 0) == " << expectedBorderColor << ")) "
1016 						<< glslResultBlock("\t", bindingArgs);
1017 				}
1018 				else if (sb.type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1019 				{
1020 					str << "	if (imageLoad(" << glslResourceName(sb.set, sb.binding) << subscript << ", ivec2(0, 0)).r == " << expectedData << ") " << glslResultBlock("\t", bindingArgs);
1021 				}
1022 				else if ((sb.type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
1023 						 (sb.type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER))
1024 				{
1025 					const auto loadOp	= (sb.type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ? "texelFetch" : "imageLoad";
1026 					const auto loopData = isNullDescriptor ? expectedData : "(" + expectedData + " + i)";
1027 
1028 					str << "	for (uint i = 0; i < " << glslFormat(bufferLoopIterations) << "; i += " << glslFormat(loopIncrement) << ") {\n"
1029 						<< "		uint value = " << loadOp << "(" << glslResourceName(sb.set, sb.binding) << subscript << ", int(i)).r;\n"
1030 						<< "		if (value == " << loopData << ") " << glslResultBlock("\t\t", bindingArgs, "i")
1031 						<< "	}\n";
1032 				}
1033 				else if ((sb.type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
1034 						 (sb.type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK))
1035 				{
1036 					const auto loopData0 = isNullDescriptor ? expectedData : "(" + expectedData + " + 4 * i + 0)";
1037 					const auto loopData1 = isNullDescriptor ? expectedData : "(" + expectedData + " + 4 * i + 1)";
1038 					const auto loopData2 = isNullDescriptor ? expectedData : "(" + expectedData + " + 4 * i + 2)";
1039 					const auto loopData3 = isNullDescriptor ? expectedData : "(" + expectedData + " + 4 * i + 3)";
1040 
1041 					str << "	for (uint i = 0; i < " << glslFormat(bufferLoopIterations) << "; i += " << glslFormat(loopIncrement) << ") {\n"
1042 						<< "		uvec4 value = " << glslResourceName(sb.set, sb.binding) << subscript << ".data[i];\n"
1043 						<< "		if (value.x == " << loopData0 << ") " << glslResultBlock("\t\t", bindingArgs, "4 * i + 0")
1044 						<< "		if (value.y == " << loopData1 << ") " << glslResultBlock("\t\t", bindingArgs, "4 * i + 1")
1045 						<< "		if (value.z == " << loopData2 << ") " << glslResultBlock("\t\t", bindingArgs, "4 * i + 2")
1046 						<< "		if (value.w == " << loopData3 << ") " << glslResultBlock("\t\t", bindingArgs, "4 * i + 3")
1047 						<< "	}\n";
1048 				}
1049 				else if (sb.type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1050 				{
1051 					const auto loopData = isNullDescriptor ? expectedData : "(" + expectedData + " + i)";
1052 
1053 					str << "	for (uint i = 0; i < " << glslFormat(bufferLoopIterations) << "; i += " << glslFormat(loopIncrement) << ") {\n"
1054 						<< "		uint value = " << glslResourceName(sb.set, sb.binding) << subscript << ".data[i];\n"
1055 						<< "		if (value == " << loopData << ") " << glslResultBlock("\t\t", bindingArgs, "i")
1056 						<< "	}\n";
1057 				}
1058 				else
1059 				{
1060 					DE_ASSERT(0);
1061 				}
1062 			}
1063 		}
1064 	}
1065 	else if (params.variant == TestVariant::ROBUST_BUFFER_ACCESS)
1066 	{
1067 		// With robust buffer tests, the buffer is always filled with zeros and we read with an offset that will
1068 		// eventually cause us to read past the end of the buffer.
1069 
1070 		for (const auto& sb : simpleBindings)
1071 		{
1072 			if (sb.isResultBuffer || sb.isRayTracingAS)
1073 			{
1074 				// Used by other bindings.
1075 				continue;
1076 			}
1077 
1078 			const deUint32 bufferLoopIterations	= getBufferLoopIterations(sb.type);
1079 			const deUint32 loopIncrement		= bufferLoopIterations / (ConstChecksPerBuffer - 1);
1080 			const auto	   iterationOffsetStr	= glslFormat(bufferLoopIterations / 2);
1081 
1082 			// Ensure we won't miss the last check (the index will always be less than the buffer length).
1083 			DE_ASSERT((bufferLoopIterations == 0) || ((bufferLoopIterations % (ConstChecksPerBuffer - 1)) != 0));
1084 
1085 			for (deUint32 arrayIndex = 0; arrayIndex < sb.count; ++arrayIndex)
1086 			{
1087 				const auto bindingArgs  = glslFormat(packBindingArgs(sb.set, sb.binding, sb.inputAttachmentIndex + arrayIndex));
1088 				const auto& subscript   = (sb.count > 1) ? "[" + std::to_string(arrayIndex) + "]" : "";
1089 
1090 				switch (sb.type)
1091 				{
1092 				case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1093 					str << "	for (uint i = 0; i < " << glslFormat(bufferLoopIterations) << ";  i += " << glslFormat(loopIncrement) << ") {\n"
1094 						<< "		if (texelFetch(" << glslResourceName(sb.set, sb.binding) << subscript << ", int(i + " << iterationOffsetStr << ")).r == 0) " << glslResultBlock("\t\t", bindingArgs, "i + " + iterationOffsetStr)
1095 						<< "	}\n";
1096 					break;
1097 
1098 				case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1099 					str << "	for (uint i = 0; i < " << glslFormat(bufferLoopIterations) << ";  i += " << glslFormat(loopIncrement) << ") {\n"
1100 						<< "		if (imageLoad(" << glslResourceName(sb.set, sb.binding) << subscript << ", int(i + " << iterationOffsetStr << ")).r == 0) " << glslResultBlock("\t\t", bindingArgs, "i + " + iterationOffsetStr)
1101 						<< "	}\n";
1102 					break;
1103 
1104 				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1105 					str << "	for (uint i = 0; i < " << glslFormat(bufferLoopIterations) << ";  i += " << glslFormat(loopIncrement) << ") {\n"
1106 						<< "		if (" << glslResourceName(sb.set, sb.binding) << subscript << ".data[i + " << iterationOffsetStr << "].x == 0) " << glslResultBlock("\t\t", bindingArgs, "4 * i + " + iterationOffsetStr + " + 0")
1107 						<< "		if (" << glslResourceName(sb.set, sb.binding) << subscript << ".data[i + " << iterationOffsetStr << "].y == 0) " << glslResultBlock("\t\t", bindingArgs, "4 * i + " + iterationOffsetStr + " + 1")
1108 						<< "		if (" << glslResourceName(sb.set, sb.binding) << subscript << ".data[i + " << iterationOffsetStr << "].z == 0) " << glslResultBlock("\t\t", bindingArgs, "4 * i + " + iterationOffsetStr + " + 2")
1109 						<< "		if (" << glslResourceName(sb.set, sb.binding) << subscript << ".data[i + " << iterationOffsetStr << "].w == 0) " << glslResultBlock("\t\t", bindingArgs, "4 * i + " + iterationOffsetStr + " + 3")
1110 						<< "	}\n";
1111 					break;
1112 
1113 				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1114 					str << "	for (uint i = 0; i < " << glslFormat(bufferLoopIterations) << ";  i += " << glslFormat(loopIncrement) << ") {\n"
1115 						<< "		if (" << glslResourceName(sb.set, sb.binding) << subscript << ".data[i + " << iterationOffsetStr << "] == 0) " << glslResultBlock("\t\t", bindingArgs, "i + " + iterationOffsetStr)
1116 						<< "	}\n";
1117 					break;
1118 
1119 				default:
1120 					DE_ASSERT(0);
1121 					break;
1122 				}
1123 			}
1124 		}
1125 	}
1126 	else if (params.variant == TestVariant::MAX)
1127 	{
1128 		std::vector<deUint32> samplerIndices;
1129 		std::vector<deUint32> imageIndices;
1130 
1131 		for (deUint32 i = 0; i < u32(simpleBindings.size()); ++i)
1132 		{
1133 			const auto& binding = simpleBindings[i];
1134 
1135 			if (binding.type == VK_DESCRIPTOR_TYPE_SAMPLER)
1136 			{
1137 				samplerIndices.emplace_back(i);
1138 			}
1139 			else if (binding.type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1140 			{
1141 				imageIndices.emplace_back(i);
1142 			}
1143 			// Ignore other descriptors, if any.
1144 		}
1145 
1146 		// Ensure that all samplers and images are accessed at least once. If we run out of one, simply reuse it.
1147 
1148 		const auto maxIndex = deMaxu32(u32(samplerIndices.size()), u32(imageIndices.size()));
1149 
1150 		for (deUint32 index = 0; index < maxIndex; ++index)
1151 		{
1152 			const auto& samplerBinding = simpleBindings[samplerIndices[index % samplerIndices.size()]];
1153 			const auto& imageBinding   = simpleBindings[imageIndices[index % imageIndices.size()]];
1154 
1155 			const auto expectedData		  = glslFormat(getExpectedData(params.hash, imageBinding.set, imageBinding.binding, 0));
1156 			const auto imageBindingArgs   = glslFormat(packBindingArgs(imageBinding.set, imageBinding.binding, 0));
1157 			const auto samplerBindingArgs = glslFormat(packBindingArgs(samplerBinding.set, samplerBinding.binding, 0));
1158 
1159 			std::stringstream samplerStr;
1160 			samplerStr << "usampler2D("
1161 				<< glslResourceName(imageBinding.set, imageBinding.binding) << ", "
1162 				<< glslResourceName(samplerBinding.set, samplerBinding.binding) << ")";
1163 
1164 			str << "	if ((textureLod(" << samplerStr.str() << ", vec2(0, 0), 0).r == " << expectedData << ") &&\n"
1165 				<< "	    (textureLod(" << samplerStr.str() << ", vec2(-1, 0), 0) == uvec4(0, 0, 0, 1))) "
1166 				<< glslResultBlock("\t", imageBindingArgs, samplerBindingArgs);
1167 		}
1168 	}
1169 	else if (params.variant == TestVariant::EMBEDDED_IMMUTABLE_SAMPLERS)
1170 	{
1171 		// The first few sets contain only samplers.
1172 		// Then the last set contains only images.
1173 		// Optionally, the last binding of that set is the compute result buffer.
1174 
1175 		deUint32 firstImageIndex = 0;
1176 		deUint32 lastImageIndex = 0;
1177 
1178 		for (deUint32 i = 0; i < u32(simpleBindings.size()); ++i)
1179 		{
1180 			const auto& binding = simpleBindings[i];
1181 
1182 			if (binding.type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1183 			{
1184 				if (firstImageIndex == 0)
1185 				{
1186 					firstImageIndex = i;
1187 				}
1188 
1189 				lastImageIndex = i;
1190 			}
1191 		}
1192 
1193 		DE_ASSERT(firstImageIndex == (lastImageIndex + 1 - firstImageIndex));	// same number of images and samplers
1194 
1195 		for (deUint32 imageIndex = firstImageIndex; imageIndex <= lastImageIndex; ++imageIndex)
1196 		{
1197 			const auto& imageBinding = simpleBindings[imageIndex];
1198 			const auto expectedData	 = glslFormat(getExpectedData(params.hash, imageBinding.set, imageBinding.binding, 0));
1199 			const auto bindingArgs	 = glslFormat(packBindingArgs(imageBinding.set, imageBinding.binding, 0));
1200 
1201 			DE_ASSERT(imageBinding.type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
1202 
1203 			const auto& samplerBinding	  = simpleBindings[imageIndex - firstImageIndex];
1204 			const auto samplerBindingArgs = glslFormat(packBindingArgs(samplerBinding.set, samplerBinding.binding, 0));
1205 
1206 			std::stringstream samplerStr;
1207 			samplerStr << "usampler2D("
1208 				<< glslResourceName(imageBinding.set, imageBinding.binding) << ", "
1209 				<< glslResourceName(samplerBinding.set, samplerBinding.binding) << ")";
1210 
1211 			str << "	if ((textureLod(" << samplerStr.str() << ", vec2(0, 0), 0).r == " << expectedData << ") &&\n"
1212 				<< "	    (textureLod(" << samplerStr.str() << ", vec2(-1, 0), 0) == uvec4(0, 0, 0, 1))) "
1213 				<< glslResultBlock("\t", bindingArgs, samplerBindingArgs);
1214 		}
1215 	}
1216 	else
1217 	{
1218 		TCU_THROW(InternalError, "Not implemented");
1219 	}
1220 
1221 	// Compute shaders write the result to a storage buffer.
1222 	const deUint32 computeResultBufferIndex = getResultBufferIndex(simpleBindings);
1223 
1224 	if (computeResultBufferIndex != INDEX_INVALID)
1225 	{
1226 		DE_ASSERT(params.isCompute() || params.isRayTracing());
1227 		const auto& resultSb = simpleBindings[computeResultBufferIndex];
1228 
1229 		str << "	" << glslResourceName(resultSb.set, resultSb.binding) << ".data[0] = result.x;\n";
1230 		str << "	" << glslResourceName(resultSb.set, resultSb.binding) << ".data[1] = result.y;\n";
1231 		str << "	" << glslResourceName(resultSb.set, resultSb.binding) << ".data[2] = result.z;\n";
1232 		str << "	" << glslResourceName(resultSb.set, resultSb.binding) << ".data[3] = result.w;\n";
1233 	}
1234 
1235 	return str.str();
1236 }
1237 
1238 // Base class for all test cases.
1239 class DescriptorBufferTestCase : public TestCase
1240 {
1241 public:
DescriptorBufferTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & params)1242 	DescriptorBufferTestCase(
1243 		tcu::TestContext& testCtx,
1244 		const std::string& name,
1245 		const std::string& description,
1246 		const TestParams& params)
1247 
1248 		: TestCase(testCtx, name, description)
1249 		, m_params(params)
1250 		, m_rng(params.hash)
1251 	{
1252 	}
1253 
1254 	void			delayedInit		();
1255 	void			initPrograms	(vk::SourceCollections&				programCollection) const;
1256 	void			initPrograms	(vk::SourceCollections&				programCollection,
1257 									 const std::vector<SimpleBinding>&	simpleBinding,
1258 									 bool								accStruct,
1259 									 bool								addService) const;
1260 	TestInstance*	createInstance	(Context& context) const;
1261 	void			checkSupport	(Context& context) const;
1262 
1263 private:
1264 	const TestParams			m_params;
1265 	de::Random					m_rng;
1266 	std::vector<SimpleBinding>	m_simpleBindings;
1267 };
1268 
1269 // Based on the basic test parameters, this function creates a number of sets/bindings that will be tested.
delayedInit()1270 void DescriptorBufferTestCase::delayedInit()
1271 {
1272 	if ((m_params.variant == TestVariant::SINGLE) ||
1273 		(m_params.variant == TestVariant::CAPTURE_REPLAY))
1274 	{
1275 		// Creates a single set with a single binding, unless additional helper resources are required.
1276 		{
1277 			SimpleBinding sb {};
1278 			sb.set					= 0;
1279 			sb.binding				= 0;
1280 			sb.type					= m_params.descriptor;
1281 			sb.count				= 1;
1282 
1283 			// For inline uniforms we still use count = 1. The byte size is implicit in our tests.
1284 
1285 			m_simpleBindings.emplace_back(sb);
1286 		}
1287 
1288 		// Sampled images require a sampler as well.
1289 		if (m_params.descriptor == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1290 		{
1291 			SimpleBinding sb {};
1292 			sb.set					= 0;
1293 			sb.binding				= u32(m_simpleBindings.size());
1294 			sb.type					= VK_DESCRIPTOR_TYPE_SAMPLER;
1295 			sb.count				= 1;
1296 
1297 			m_simpleBindings.emplace_back(sb);
1298 		}
1299 		else if (m_params.isCaptureReplayDescriptor(VK_DESCRIPTOR_TYPE_SAMPLER))
1300 		{
1301 			// Samplers are usually tested implicitly, but with capture replay they are the target of specific API commands.
1302 			// Add a sampled image to acompany the sampler.
1303 
1304 			SimpleBinding sb {};
1305 			sb.set					= 0;
1306 			sb.binding				= u32(m_simpleBindings.size());
1307 			sb.type					= VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1308 			sb.count				= 1;
1309 
1310 			m_simpleBindings.emplace_back(sb);
1311 		}
1312 
1313 		// For compute shaders add a result buffer as the last binding of the first set.
1314 		if (m_params.isCompute() || m_params.isRayTracing())
1315 		{
1316 			SimpleBinding sb {};
1317 			sb.set				= 0;
1318 			sb.binding			= u32(m_simpleBindings.size());
1319 			sb.type				= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1320 			sb.count			= 1;
1321 			sb.isResultBuffer	= true;
1322 			sb.isRayTracingAS	= false;
1323 
1324 			m_simpleBindings.emplace_back(sb);
1325 
1326 			if (m_params.isRayTracing())
1327 			{
1328 				SimpleBinding sba{};
1329 				sba.set				= 0;
1330 				sba.binding			= u32(m_simpleBindings.size());
1331 				sba.type			= VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
1332 				sba.count			= 1;
1333 				sba.isResultBuffer	= false;
1334 				sba.isRayTracingAS	= true;
1335 
1336 				m_simpleBindings.emplace_back(sba);
1337 			}
1338 		}
1339 	}
1340 	else if ((m_params.variant == TestVariant::MULTIPLE) ||
1341 			 (m_params.variant == TestVariant::PUSH_DESCRIPTOR) ||
1342 			 (m_params.variant == TestVariant::PUSH_TEMPLATE) ||
1343 			 (m_params.variant == TestVariant::ROBUST_BUFFER_ACCESS) ||
1344 			 (m_params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR))
1345 	{
1346 		// Generate a descriptor set for each descriptor buffer binding.
1347 		// Within a set, add bindings for each descriptor type. Bindings may have 1-3 array elements.
1348 		// In this test we include sampler descriptors, they will be used with sampled images, if needed.
1349 
1350 		// NOTE: For implementation simplicity, this test doesn't limit the number of descriptors accessed
1351 		// in the shaders, which may not work on some implementations.
1352 
1353 		// Don't overcomplicate the test logic
1354 		DE_ASSERT(!m_params.isPushDescriptorTest() || (m_params.setsPerBuffer == 1));
1355 
1356 		// Add one more set for push descriptors (if used)
1357 		const auto	numSets				= (m_params.bufferBindingCount * m_params.setsPerBuffer) + (m_params.isPushDescriptorTest() ? 1 : 0);
1358 		deUint32	attachmentIndex		= 0;
1359 
1360 		// One set per buffer binding
1361 		for (deUint32 set = 0; set < numSets; ++set)
1362 		{
1363 			std::vector<VkDescriptorType> choiceDescriptors;
1364 			choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER);
1365 			choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
1366 			choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
1367 			choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1368 
1369 			if (m_params.variant != TestVariant::ROBUST_BUFFER_ACCESS)
1370 			{
1371 				choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_SAMPLER);
1372 				choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1373 				choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
1374 				choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
1375 
1376 				if (m_params.variant != TestVariant::ROBUST_NULL_DESCRIPTOR || (m_params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR && m_params.isAccelerationStructure()))
1377 					choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);	// will be replaced with VK_DESCRIPTOR_TYPE_STORAGE_BUFFER if unsupported
1378 
1379 				if ((m_params.variant != TestVariant::ROBUST_NULL_DESCRIPTOR) &&
1380 					(!m_params.isPushDescriptorTest() || (set != m_params.pushDescriptorSetIndex)))
1381 				{
1382 					choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK);
1383 				}
1384 
1385 				if (m_params.stage == VK_SHADER_STAGE_FRAGMENT_BIT)
1386 				{
1387 					choiceDescriptors.emplace_back(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
1388 				}
1389 			}
1390 
1391 			// Randomize the order
1392 			m_rng.shuffle(choiceDescriptors.begin(), choiceDescriptors.end());
1393 
1394 			for (deUint32 binding = 0; binding < u32(choiceDescriptors.size()); ++binding)
1395 			{
1396 				SimpleBinding sb {};
1397 				sb.set		= set;
1398 				sb.binding	= binding;
1399 				sb.type		= choiceDescriptors[binding];
1400 				sb.count	= 1 + ((sb.type != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) ? m_rng.getUint32() % ConstMaxDescriptorArraySize : 0);
1401 
1402 				// For inline uniforms we still use count = 1. The byte size is implicit in our tests.
1403 
1404 				if (sb.type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
1405 				{
1406 					sb.inputAttachmentIndex = attachmentIndex;
1407 					attachmentIndex += sb.count;
1408 				}
1409 
1410 				m_simpleBindings.emplace_back(sb);
1411 			}
1412 
1413 			// For compute shaders add a result buffer as the last binding of the first set.
1414 			if (set == 0 && (m_params.isCompute() || m_params.isRayTracing()))
1415 			{
1416 				SimpleBinding sb {};
1417 				sb.set				= set;
1418 				sb.binding			= u32(m_simpleBindings.size());
1419 				sb.type				= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1420 				sb.count			= 1;
1421 				sb.isResultBuffer	= true;
1422 				sb.isRayTracingAS	= false;
1423 
1424 				m_simpleBindings.emplace_back(sb);
1425 
1426 				if (m_params.isRayTracing())
1427 				{
1428 					SimpleBinding sba{};
1429 					sba.set				= set;
1430 					sba.binding			= u32(m_simpleBindings.size());
1431 					sba.type			= VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
1432 					sba.count			= 1;
1433 					sba.isResultBuffer	= false;
1434 					sba.isRayTracingAS	= true;
1435 
1436 					m_simpleBindings.emplace_back(sba);
1437 				}
1438 			}
1439 		}
1440 	}
1441 	else if (m_params.variant == TestVariant::MAX)
1442 	{
1443 		// Create sampler- and resource-only sets, up to specified maxiumums.
1444 		// Each set will get its own descriptor buffer binding.
1445 
1446 		deUint32 set		  = 0;
1447 		deUint32 samplerIndex = 0;
1448 		deUint32 imageIndex	  = 0;
1449 
1450 		for (;;)
1451 		{
1452 			SimpleBinding sb {};
1453 			sb.binding	= 0;
1454 			sb.count	= 1;
1455 			sb.set      = set;	// save the original set index here
1456 
1457 			if (samplerIndex < m_params.samplerBufferBindingCount)
1458 			{
1459 				sb.set  = set;
1460 				sb.type	= VK_DESCRIPTOR_TYPE_SAMPLER;
1461 
1462 				m_simpleBindings.emplace_back(sb);
1463 
1464 				++set;
1465 				++samplerIndex;
1466 			}
1467 
1468 			if (imageIndex < m_params.resourceBufferBindingCount)
1469 			{
1470 				sb.set  = set;
1471 				sb.type	= VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1472 
1473 				m_simpleBindings.emplace_back(sb);
1474 
1475 				// Put the result buffer in the first resource set
1476 				if ((imageIndex == 0) && (m_params.isCompute() || m_params.isRayTracing()))
1477 				{
1478 					sb.binding			= 1;
1479 					sb.type				= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1480 					sb.isResultBuffer	= true;
1481 
1482 					m_simpleBindings.emplace_back(sb);
1483 
1484 					if (m_params.isRayTracing())
1485 					{
1486 						sb.binding			= 2;
1487 						sb.type				= VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
1488 						sb.isResultBuffer	= false;
1489 						sb.isRayTracingAS	= true;
1490 
1491 						m_simpleBindings.emplace_back(sb);
1492 					}
1493 				}
1494 
1495 				++set;
1496 				++imageIndex;
1497 			}
1498 
1499 			if (sb.set == set)
1500 			{
1501 				// We didn't add a new set, so we must be done.
1502 				break;
1503 			}
1504 		}
1505 	}
1506 	else if (m_params.variant == TestVariant::EMBEDDED_IMMUTABLE_SAMPLERS)
1507 	{
1508 		// Create a number of sampler-only sets across several descriptor buffers, they will be used as embedded
1509 		// immutable sampler buffers. Finally, add a set with images that use these samplers.
1510 
1511 		// Buffer index maps to a set with embedded immutable samplers
1512 		for (deUint32 bufferIndex = 0; bufferIndex < m_params.embeddedImmutableSamplerBufferBindingCount; ++bufferIndex)
1513 		{
1514 			for (deUint32 samplerIndex = 0; samplerIndex < m_params.embeddedImmutableSamplersPerBuffer; ++samplerIndex)
1515 			{
1516 				SimpleBinding sb {};
1517 				sb.set							= bufferIndex;
1518 				sb.binding						= samplerIndex;
1519 				sb.count						= 1;
1520 				sb.type							= VK_DESCRIPTOR_TYPE_SAMPLER;
1521 				sb.isEmbeddedImmutableSampler	= true;
1522 
1523 				m_simpleBindings.emplace_back(sb);
1524 			}
1525 		}
1526 
1527 		// After the samplers come the images
1528 		if (!m_simpleBindings.empty())
1529 		{
1530 			SimpleBinding sb {};
1531 			sb.set      = m_simpleBindings.back().set + 1;
1532 			sb.count	= 1;
1533 
1534 			const auto numSamplers = m_params.embeddedImmutableSamplerBufferBindingCount * m_params.embeddedImmutableSamplersPerBuffer;
1535 
1536 			for (deUint32 samplerIndex = 0; samplerIndex < numSamplers; ++samplerIndex)
1537 			{
1538 				sb.type		= VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1539 				sb.binding	= samplerIndex;
1540 
1541 				m_simpleBindings.emplace_back(sb);
1542 			}
1543 
1544 			if (m_params.isCompute() || m_params.isRayTracing())
1545 			{
1546 				// Append the result buffer after the images
1547 				sb.binding			+= 1;
1548 				sb.type				= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1549 				sb.isResultBuffer	= true;
1550 
1551 				m_simpleBindings.emplace_back(sb);
1552 
1553 				if (m_params.isRayTracing())
1554 				{
1555 					sb.binding			+= 1;
1556 					sb.type				= VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
1557 					sb.isResultBuffer	= false;
1558 					sb.isRayTracingAS	= true;
1559 
1560 					m_simpleBindings.emplace_back(sb);
1561 				}
1562 			}
1563 		}
1564 	}
1565 }
1566 
1567 // Generate shaders for both acceleration structures and without them
initPrograms(vk::SourceCollections & programs) const1568 void DescriptorBufferTestCase::initPrograms (vk::SourceCollections& programs) const
1569 {
1570 	const bool accStruct	= m_params.isAccelerationStructureObligatory() || m_params.isAccelerationStructureOptional();
1571 
1572 	initPrograms(programs, m_simpleBindings, accStruct, true);
1573 
1574 	if (accStruct)
1575 	{
1576 		std::vector<SimpleBinding>	simpleBindings(m_simpleBindings);
1577 
1578 		for (auto& simpleBinding : simpleBindings)
1579 			if (simpleBinding.type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1580 				simpleBinding.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1581 
1582 		initPrograms(programs, simpleBindings, false, false);
1583 	}
1584 }
1585 
1586 // Initialize GLSL shaders used by all test cases.
initPrograms(vk::SourceCollections & programs,const std::vector<SimpleBinding> & simpleBindings,bool accStruct,bool addService) const1587 void DescriptorBufferTestCase::initPrograms (vk::SourceCollections& programs, const std::vector<SimpleBinding>& simpleBindings, bool accStruct, bool addService) const
1588 {
1589 	// For vertex pipelines, a verification variable (in_result/out_result) is passed
1590 	// through shader interfaces, until it can be output as a color write.
1591 	//
1592 	// Compute shaders still declare a "result" variable to help unify the verification logic.
1593 	std::string extentionDeclarations	= std::string(glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460)) + "\n"
1594 										+ (m_params.isRayTracing() ? "#extension GL_EXT_ray_tracing : require\n" : "");
1595 
1596 	if (m_params.isGraphics())
1597 	{
1598 		std::string srcDeclarations;
1599 		std::string srcVerification;
1600 		std::string suffix;
1601 
1602 		if (m_params.stage == VK_SHADER_STAGE_VERTEX_BIT)
1603 		{
1604 			srcDeclarations = glslGlobalDeclarations(m_params, simpleBindings, accStruct) + "\n";
1605 			srcVerification = glslOutputVerification(m_params, simpleBindings, accStruct) + "\n";
1606 			suffix			= accStruct ? "_as" : "";
1607 		}
1608 
1609 		std::ostringstream str;
1610 		str << extentionDeclarations
1611 			<< srcDeclarations <<
1612 			"\n"
1613 			"layout(location = 0) out uvec4 out_result;\n"
1614 			"\n"
1615 			"void main (void) {\n"
1616 			"	switch(gl_VertexIndex) {\n"
1617 			"		case 0: gl_Position = vec4(-1, -1, 0, 1); break;\n"
1618 			"		case 1: gl_Position = vec4(-1,  1, 0, 1); break;\n"
1619 			"		case 2: gl_Position = vec4( 1, -1, 0, 1); break;\n"
1620 			"\n"
1621 			"		case 3: gl_Position = vec4( 1,  1, 0, 1); break;\n"
1622 			"		case 4: gl_Position = vec4( 1, -1, 0, 1); break;\n"
1623 			"		case 5: gl_Position = vec4(-1,  1, 0, 1); break;\n"
1624 			"	}\n"
1625 			"\n"
1626 			"	uvec4 result = uvec4(0);\n"
1627 			"\n"
1628 			<< srcVerification <<
1629 			"\n"
1630 			"	out_result = result;\n"
1631 			"}\n";
1632 
1633 		if (addService || !srcDeclarations.empty()) programs.glslSources.add("vert" + suffix) << glu::VertexSource(str.str());
1634 	}
1635 
1636 	if (m_params.isGraphics())
1637 	{
1638 		std::string srcDeclarations;
1639 		std::string srcVerification;
1640 		std::string suffix;
1641 
1642 		if (m_params.stage == VK_SHADER_STAGE_FRAGMENT_BIT)
1643 		{
1644 			srcDeclarations = glslGlobalDeclarations(m_params, simpleBindings, accStruct) + "\n";
1645 			srcVerification = glslOutputVerification(m_params, simpleBindings, accStruct) + "\n";
1646 			suffix			= accStruct ? "_as" : "";
1647 		}
1648 
1649 		std::ostringstream str;
1650 		str << extentionDeclarations
1651 			<< srcDeclarations <<
1652 			"\n"
1653 			"layout(location = 0) in flat uvec4 in_result;\n"
1654 			"\n"
1655 			"layout(location = 0) out uint out_color;\n"
1656 			"\n"
1657 			"void main (void) {\n"
1658 			"	uvec4 result = in_result;\n"
1659 			"\n"
1660 			<< srcVerification <<
1661 			"\n"
1662 			"	if (uint(gl_FragCoord.x) == 0)	out_color = result.x;\n"
1663 			"	if (uint(gl_FragCoord.x) == 1)	out_color = result.y;\n"
1664 			"	if (uint(gl_FragCoord.x) == 2)	out_color = result.z;\n"
1665 			"	if (uint(gl_FragCoord.x) == 3)	out_color = result.w;\n"
1666 			"}\n";
1667 
1668 		if (addService || !srcDeclarations.empty()) programs.glslSources.add("frag" + suffix) << glu::FragmentSource(str.str());
1669 	}
1670 
1671 	if (m_params.isGeometry())
1672 	{
1673 		std::string srcDeclarations = glslGlobalDeclarations(m_params, simpleBindings, accStruct) + "\n";
1674 		std::string srcVerification = glslOutputVerification(m_params, simpleBindings, accStruct) + "\n";
1675 		std::string suffix			= accStruct ? "_as" : "";
1676 
1677 		std::ostringstream str;
1678 		str << extentionDeclarations
1679 			<< srcDeclarations <<
1680 			"\n"
1681 			"layout(triangles) in;\n"
1682 			"layout(triangle_strip, max_vertices = 3) out;\n"
1683 			"\n"
1684 			"layout(location = 0) in  uvec4 in_result[];\n"
1685 			"layout(location = 0) out uvec4 out_result;\n"
1686 			"\n"
1687 			"void main (void) {\n"
1688 			"	for (uint i = 0; i < gl_in.length(); ++i) {\n"
1689 			"		gl_Position = gl_in[i].gl_Position;\n"
1690 			"\n"
1691 			"		uvec4 result = in_result[i];\n"
1692 			"\n"
1693 			<< srcVerification <<
1694 			"\n"
1695 			"		out_result = result;\n"
1696 			"\n"
1697 			"		EmitVertex();\n"
1698 			"	}\n"
1699 			"}\n";
1700 
1701 		if (addService || !srcDeclarations.empty()) programs.glslSources.add("geom" + suffix) << glu::GeometrySource(str.str());
1702 	}
1703 
1704 	if (m_params.isTessellation())
1705 	{
1706 		std::string srcDeclarations;
1707 		std::string srcVerification;
1708 		std::string suffix;
1709 
1710 		if (m_params.stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1711 		{
1712 			srcDeclarations = glslGlobalDeclarations(m_params, simpleBindings, accStruct) + "\n";
1713 			srcVerification = glslOutputVerification(m_params, simpleBindings, accStruct) + "\n";
1714 			suffix			= accStruct ? "_as" : "";
1715 		}
1716 
1717 		std::ostringstream str;
1718 		str << extentionDeclarations <<
1719 			"#extension GL_EXT_tessellation_shader : require\n"
1720 			<< srcDeclarations <<
1721 			"\n"
1722 			"layout(vertices = 3) out;\n"
1723 			"\n"
1724 			"layout(location = 0) in  uvec4 in_result[];\n"
1725 			"layout(location = 0) out uvec4 out_result[];\n"
1726 			"\n"
1727 			"void main (void) {\n"
1728 			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1729 			"	\n"
1730 			"	gl_TessLevelOuter[0] = 1.0;\n"
1731 			"	gl_TessLevelOuter[1] = 1.0;\n"
1732 			"	gl_TessLevelOuter[2] = 1.0;\n"
1733 			"	gl_TessLevelInner[0] = 1.0;\n"
1734 			"\n"
1735 			"	uvec4 result = in_result[gl_InvocationID];\n"
1736 			"\n"
1737 			<< srcVerification <<
1738 			"\n"
1739 			"	out_result[gl_InvocationID] = result;\n"
1740 			"}\n";
1741 
1742 		if (addService || !srcDeclarations.empty()) programs.glslSources.add("tesc" + suffix) << glu::TessellationControlSource(str.str());
1743 	}
1744 
1745 	if (m_params.isTessellation())
1746 	{
1747 		std::string srcDeclarations;
1748 		std::string srcVerification;
1749 		std::string suffix;
1750 
1751 		if (m_params.stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1752 		{
1753 			srcDeclarations = glslGlobalDeclarations(m_params, simpleBindings, accStruct) + "\n";
1754 			srcVerification = glslOutputVerification(m_params, simpleBindings, accStruct) + "\n";
1755 			suffix			= accStruct ? "_as" : "";
1756 		}
1757 
1758 		std::ostringstream str;
1759 		str << extentionDeclarations <<
1760 			"#extension GL_EXT_tessellation_shader : require\n"
1761 			<< srcDeclarations <<
1762 			"\n"
1763 			"layout(triangles) in;\n"
1764 			"\n"
1765 			"layout(location = 0) in  uvec4 in_result[];\n"
1766 			"layout(location = 0) out uvec4 out_result;\n"
1767 			"\n"
1768 			"void main (void) {\n"
1769 			"	gl_Position.xyz = gl_TessCoord.x * gl_in[0].gl_Position.xyz +\n"
1770 			"	                  gl_TessCoord.y * gl_in[1].gl_Position.xyz +\n"
1771 			"	                  gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
1772 			"	gl_Position.w   = 1.0;\n"
1773 			"\n"
1774 			"	uvec4 result = in_result[0];\n"	// Use index 0, all vertices should have the same value
1775 			"\n"
1776 			<< srcVerification <<
1777 			"\n"
1778 			"	out_result = result;\n"
1779 			"}\n";
1780 
1781 		if (addService || !srcDeclarations.empty()) programs.glslSources.add("tese" + suffix) << glu::TessellationEvaluationSource(str.str());
1782 	}
1783 
1784 	if (m_params.isCompute())
1785 	{
1786 		const std::string	suffix = accStruct ? "_as" : "";
1787 		std::ostringstream	str;
1788 		str << extentionDeclarations
1789 			<< glslGlobalDeclarations(m_params, simpleBindings, accStruct) <<
1790 			"\n"
1791 			"layout(local_size_x = 1) in;\n"
1792 			"\n"
1793 			"void main (void) {\n"
1794 			"	uvec4 result = uvec4(0);\n"
1795 			"\n"
1796 			<< glslOutputVerification(m_params, simpleBindings, accStruct) <<
1797 			"}\n";
1798 
1799 		programs.glslSources.add("comp" + suffix) << glu::ComputeSource(str.str());
1800 	}
1801 
1802 	if (m_params.isRayTracing())
1803 	{
1804 		const std::string				missPassthrough	= extentionDeclarations +
1805 			"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1806 			"\n"
1807 			"void main()\n"
1808 			"{\n"
1809 			"}\n";
1810 		const std::string				hitPassthrough	= extentionDeclarations +
1811 			"hitAttributeEXT vec3 attribs;\n"
1812 			"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1813 			"\n"
1814 			"void main()\n"
1815 			"{\n"
1816 			"}\n";
1817 		const deUint32					asIndex			= getRayTracingASIndex(simpleBindings);
1818 		const auto&						asBinding		= simpleBindings[asIndex];
1819 		const std::string				asName			= glslResourceName(asBinding.set, asBinding.binding);
1820 		const std::string				raygenCommon	= extentionDeclarations +
1821 			"layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
1822 			"layout(set = " + de::toString(asBinding.set) + ", binding = " + de::toString(asBinding.binding) + ") uniform accelerationStructureEXT " + asName + ";\n"
1823 			"\n"
1824 			"void main()\n"
1825 			"{\n"
1826 			"	uint  rayFlags = 0;\n"
1827 			"	uint  cullMask = 0xFF;\n"
1828 			"	float tmin     = 0.0f;\n"
1829 			"	float tmax     = 9.0f;\n"
1830 			"	vec3  origin   = vec3(0.0f, 0.0f, 0.0f);\n"
1831 			"	vec3  direct   = vec3(0.0f, 0.0f, -1.0f);\n"
1832 			"	traceRayEXT(" + asName + ", rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
1833 			"}\n";
1834 		const vk::ShaderBuildOptions	buildOptions	= vk::ShaderBuildOptions(programs.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1835 		const std::string				suffix			= accStruct ? "_as" : "";
1836 		const std::string				srcDeclarations	= glslGlobalDeclarations(m_params, simpleBindings, accStruct) + "\n";
1837 		const std::string				srcVerification	= "	uvec4 result = uvec4(0);\n"
1838 														+ glslOutputVerification(m_params, simpleBindings, accStruct) + "\n";
1839 
1840 		switch (m_params.stage)
1841 		{
1842 			case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
1843 			{
1844 				std::stringstream css;
1845 				css << extentionDeclarations << "\n"
1846 					<< srcDeclarations <<
1847 					"\n"
1848 					"void main()\n"
1849 					"{\n"
1850 					<< srcVerification <<
1851 					"}\n";
1852 
1853 				programs.glslSources.add("rgen" + suffix) << glu::RaygenSource(css.str()) << buildOptions;
1854 
1855 				break;
1856 			}
1857 
1858 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
1859 			{
1860 				if (addService) programs.glslSources.add("rgen") << glu::RaygenSource(raygenCommon) << buildOptions;
1861 
1862 				{
1863 					std::stringstream css;
1864 					css << extentionDeclarations << "\n"
1865 						<< srcDeclarations <<
1866 						"hitAttributeEXT vec3 attribs;\n"
1867 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1868 						"\n"
1869 						"void main()\n"
1870 						"{\n"
1871 						<< srcVerification <<
1872 						"}\n";
1873 
1874 					programs.glslSources.add("ahit" + suffix) << glu::AnyHitSource(css.str()) << buildOptions;
1875 				}
1876 
1877 				if (addService) programs.glslSources.add("chit") << glu::ClosestHitSource(hitPassthrough) << buildOptions;
1878 				if (addService) programs.glslSources.add("miss") << glu::MissSource(missPassthrough) << buildOptions;
1879 
1880 				break;
1881 			}
1882 
1883 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
1884 			{
1885 				if (addService) programs.glslSources.add("rgen") << glu::RaygenSource(raygenCommon) << buildOptions;
1886 
1887 				{
1888 					std::stringstream css;
1889 					css << extentionDeclarations << "\n"
1890 						<< srcDeclarations <<
1891 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1892 						"hitAttributeEXT vec3 attribs;\n"
1893 						"\n"
1894 						"\n"
1895 						"void main()\n"
1896 						"{\n"
1897 						<< srcVerification <<
1898 						"}\n";
1899 
1900 					programs.glslSources.add("chit" + suffix) << glu::ClosestHitSource(css.str()) << buildOptions;
1901 				}
1902 
1903 				if (addService) programs.glslSources.add("ahit") << glu::AnyHitSource(hitPassthrough) << buildOptions;
1904 				if (addService) programs.glslSources.add("miss") << glu::MissSource(missPassthrough) << buildOptions;
1905 
1906 				break;
1907 			}
1908 
1909 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
1910 			{
1911 				if (addService) programs.glslSources.add("rgen") << glu::RaygenSource(raygenCommon) << buildOptions;
1912 
1913 				{
1914 					std::stringstream css;
1915 					css << extentionDeclarations << "\n"
1916 						<< srcDeclarations <<
1917 						"hitAttributeEXT vec3 hitAttribute;\n"
1918 						"\n"
1919 						"void main()\n"
1920 						"{\n"
1921 						<< srcVerification <<
1922 						"	hitAttribute = vec3(0.0f, 0.0f, 0.0f);\n"
1923 						"	reportIntersectionEXT(1.0f, 0);\n"
1924 						"}\n";
1925 
1926 					programs.glslSources.add("sect" + suffix) << glu::IntersectionSource(css.str()) << buildOptions;
1927 				}
1928 
1929 				if (addService) programs.glslSources.add("ahit") << glu::AnyHitSource(hitPassthrough) << buildOptions;
1930 				if (addService) programs.glslSources.add("chit") << glu::ClosestHitSource(hitPassthrough) << buildOptions;
1931 				if (addService) programs.glslSources.add("miss") << glu::MissSource(missPassthrough) << buildOptions;
1932 
1933 				break;
1934 			}
1935 
1936 			case VK_SHADER_STAGE_MISS_BIT_KHR:
1937 			{
1938 				if (addService) programs.glslSources.add("rgen") << glu::RaygenSource(raygenCommon) << buildOptions;
1939 
1940 				{
1941 					std::stringstream css;
1942 					css << extentionDeclarations << "\n"
1943 						<< srcDeclarations <<
1944 						"\n"
1945 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1946 						"\n"
1947 						"void main()\n"
1948 						"{\n"
1949 						<< srcVerification <<
1950 						"}\n";
1951 
1952 					programs.glslSources.add("miss" + suffix) << glu::MissSource(css.str()) << buildOptions;
1953 				}
1954 
1955 				if (addService) programs.glslSources.add("ahit") << glu::AnyHitSource(hitPassthrough) << buildOptions;
1956 				if (addService) programs.glslSources.add("chit") << glu::ClosestHitSource(hitPassthrough) << buildOptions;
1957 
1958 				break;
1959 			}
1960 
1961 			case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
1962 			{
1963 				{
1964 					std::stringstream css;
1965 					css << extentionDeclarations << "\n"
1966 						<< (accStruct ? "#extension GL_EXT_ray_query : require\n" : "") <<
1967 						"\n"
1968 						"layout(location = 0) callableDataEXT float dummy;"
1969 						"\n"
1970 						"void main()\n"
1971 						"{\n"
1972 						"	executeCallableEXT(0, 0);\n"
1973 						"}\n";
1974 
1975 					if (addService) programs.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
1976 				}
1977 
1978 				{
1979 					std::stringstream css;
1980 					css << extentionDeclarations << "\n"
1981 						<< srcDeclarations <<
1982 						"\n"
1983 						"layout(location = 0) callableDataInEXT float dummy;"
1984 						"\n"
1985 						"void main()\n"
1986 						"{\n"
1987 						<< srcVerification <<
1988 						"}\n";
1989 
1990 					programs.glslSources.add("call" + suffix) << glu::CallableSource(css.str()) << buildOptions;
1991 				}
1992 
1993 				if (addService) programs.glslSources.add("ahit") << glu::AnyHitSource(hitPassthrough) << buildOptions;
1994 				if (addService) programs.glslSources.add("chit") << glu::ClosestHitSource(hitPassthrough) << buildOptions;
1995 				if (addService) programs.glslSources.add("miss") << glu::MissSource(missPassthrough) << buildOptions;
1996 
1997 				break;
1998 			}
1999 
2000 			default:
2001 				TCU_THROW(InternalError, "Unknown stage");
2002 		}
2003 	}
2004 }
2005 
checkSupport(Context & context) const2006 void DescriptorBufferTestCase::checkSupport (Context& context) const
2007 {
2008 	// Required to test the extension
2009 	if (!context.isDeviceFunctionalitySupported("VK_EXT_descriptor_buffer"))
2010 	{
2011 		TCU_THROW(NotSupportedError, "VK_EXT_descriptor_buffer is not supported");
2012 	}
2013 
2014 	if (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))
2015 	{
2016 		TCU_THROW(NotSupportedError, "VK_KHR_get_physical_device_properties2 is not supported");
2017 	}
2018 
2019 	if (!context.isDeviceFunctionalitySupported("VK_KHR_buffer_device_address"))
2020 	{
2021 		TCU_THROW(NotSupportedError, "VK_KHR_buffer_device_address is not supported");
2022 	}
2023 
2024 	if (!context.isDeviceFunctionalitySupported("VK_KHR_synchronization2"))
2025 	{
2026 		TCU_THROW(NotSupportedError, "VK_KHR_synchronization2 is not supported");
2027 	}
2028 
2029 	if (!context.isDeviceFunctionalitySupported("VK_EXT_descriptor_indexing"))
2030 	{
2031 		TCU_THROW(NotSupportedError, "VK_EXT_descriptor_indexing is not supported");
2032 	}
2033 
2034 	context.requireDeviceFunctionality("VK_KHR_buffer_device_address");
2035 	context.requireDeviceFunctionality("VK_KHR_maintenance4");
2036 
2037 	// Optional
2038 
2039 	if ((m_params.descriptor == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) &&
2040 		!context.isDeviceFunctionalitySupported("VK_EXT_inline_uniform_block"))
2041 	{
2042 		TCU_THROW(NotSupportedError, "VK_EXT_inline_uniform_block is not supported");
2043 	}
2044 
2045 	const auto& descriptorBufferFeatures = *findStructure<VkPhysicalDeviceDescriptorBufferFeaturesEXT>(&context.getDeviceFeatures2());
2046 	const auto& descriptorBufferProps	 = *findStructure<VkPhysicalDeviceDescriptorBufferPropertiesEXT>(&context.getDeviceProperties2());
2047 
2048 	if (!descriptorBufferFeatures.descriptorBuffer)
2049 	{
2050 		TCU_THROW(NotSupportedError, "descriptorBufferFeatures.descriptorBuffer is not supported");
2051 	}
2052 
2053 	if (m_params.variant == TestVariant::CAPTURE_REPLAY)
2054 	{
2055 		if (descriptorBufferFeatures.descriptorBufferCaptureReplay == VK_FALSE)
2056 		{
2057 			TCU_THROW(NotSupportedError, "descriptorBufferCaptureReplay feature is not supported");
2058 		}
2059 
2060 		if ((m_params.subcase == SubCase::CAPTURE_REPLAY_CUSTOM_BORDER_COLOR) &&
2061 			!context.isDeviceFunctionalitySupported("VK_EXT_custom_border_color"))
2062 		{
2063 			TCU_THROW(NotSupportedError, "VK_EXT_custom_border_color is not supported");
2064 		}
2065 	}
2066 
2067 	if (m_params.isTessellation() &&
2068 		(context.getDeviceFeatures().tessellationShader == VK_FALSE))
2069 	{
2070 		TCU_THROW(NotSupportedError, "tessellationShader feature is not supported");
2071 	}
2072 	else if (m_params.isGeometry() &&
2073 		(context.getDeviceFeatures().geometryShader == VK_FALSE))
2074 	{
2075 		TCU_THROW(NotSupportedError, "geometryShader feature is not supported");
2076 	}
2077 
2078 	if (m_params.bufferBindingCount * m_params.setsPerBuffer > context.getDeviceProperties().limits.maxBoundDescriptorSets)
2079 		TCU_THROW(NotSupportedError, "Test requires more descriptor sets than specified in maxBoundDescriptorSets");
2080 
2081 	// Test case specific
2082 	if (m_params.isPushDescriptorTest())
2083 	{
2084 		context.requireDeviceFunctionality("VK_KHR_push_descriptor");
2085 
2086 		if (descriptorBufferFeatures.descriptorBufferPushDescriptors == VK_FALSE)
2087 		{
2088 			TCU_THROW(NotSupportedError, "Require descriptorBufferFeatures.descriptorBufferPushDescriptors");
2089 		}
2090 
2091 		if (m_params.bufferBindingCount + 1 > context.getDeviceProperties().limits.maxBoundDescriptorSets)
2092 			TCU_THROW(NotSupportedError, "Test requires more descriptor sets than specified in maxBoundDescriptorSets");
2093 
2094 		if (m_params.subcase == SubCase::SINGLE_BUFFER)
2095 		{
2096 			if (descriptorBufferProps.bufferlessPushDescriptors)
2097 				TCU_THROW(NotSupportedError, "Require bufferlessPushDescriptors to be false");
2098 		}
2099 		else
2100 		{
2101 			if (m_params.samplerBufferBindingCount + 1 > descriptorBufferProps.maxSamplerDescriptorBufferBindings)
2102 			{
2103 				TCU_THROW(NotSupportedError, "maxSamplerDescriptorBufferBindings is too small");
2104 			}
2105 
2106 			if (m_params.resourceBufferBindingCount + 1 > descriptorBufferProps.maxResourceDescriptorBufferBindings)
2107 			{
2108 				TCU_THROW(NotSupportedError, "maxResourceDescriptorBufferBindings is too small");
2109 			}
2110 		}
2111 	}
2112 
2113 	if (m_params.bufferBindingCount > descriptorBufferProps.maxDescriptorBufferBindings)
2114 	{
2115 		TCU_THROW(NotSupportedError, "maxDescriptorBufferBindings is too small");
2116 	}
2117 
2118 	if (m_params.samplerBufferBindingCount > descriptorBufferProps.maxSamplerDescriptorBufferBindings)
2119 	{
2120 		TCU_THROW(NotSupportedError, "maxSamplerDescriptorBufferBindings is too small");
2121 	}
2122 
2123 	if (m_params.resourceBufferBindingCount > descriptorBufferProps.maxResourceDescriptorBufferBindings)
2124 	{
2125 		TCU_THROW(NotSupportedError, "maxResourceDescriptorBufferBindings is too small");
2126 	}
2127 
2128 	if ((m_params.variant == TestVariant::ROBUST_BUFFER_ACCESS) ||
2129 		(m_params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR))
2130 	{
2131 		if (context.isDeviceFunctionalitySupported("VK_EXT_robustness2"))
2132 		{
2133 			VkPhysicalDeviceFeatures2				features2			= initVulkanStructure();
2134 			VkPhysicalDeviceRobustness2FeaturesEXT	robustness2Features = initVulkanStructure();
2135 
2136 			features2.pNext = &robustness2Features;
2137 
2138 			context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2139 
2140 			if ((m_params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR) &&
2141 				(robustness2Features.nullDescriptor == VK_FALSE))
2142 			{
2143 				TCU_THROW(NotSupportedError, "robustness2 nullDescriptor is not supported");
2144 			}
2145 
2146 			DE_ASSERT(features2.features.robustBufferAccess);
2147 		}
2148 		else if (m_params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR)
2149 		{
2150 			TCU_THROW(NotSupportedError, "VK_EXT_robustness2 is not supported");
2151 		}
2152 		else if (m_params.variant == TestVariant::ROBUST_BUFFER_ACCESS)
2153 		{
2154 			VkPhysicalDeviceFeatures features {};
2155 			context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
2156 
2157 			if (features.robustBufferAccess == VK_FALSE)
2158 			{
2159 				TCU_THROW(NotSupportedError, "robustBufferAccess is not supported");
2160 			}
2161 		}
2162 	}
2163 
2164 	if ((m_params.descriptor == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) ||
2165 		(m_params.variant == TestVariant::MULTIPLE) ||
2166 		m_params.isPushDescriptorTest())
2167 	{
2168 		const auto& inlineUniformBlockFeatures = context.getInlineUniformBlockFeatures();
2169 
2170 		if (!inlineUniformBlockFeatures.inlineUniformBlock)
2171 		{
2172 			TCU_THROW(NotSupportedError, "inlineUniformBlock is required");
2173 		}
2174 	}
2175 
2176 	if (m_params.variant == TestVariant::MULTIPLE)
2177 	{
2178 		const VkPhysicalDeviceVulkan13Properties& vulkan13properties = *findStructure<VkPhysicalDeviceVulkan13Properties>(&context.getDeviceProperties2());
2179 
2180 		if (m_params.bufferBindingCount > vulkan13properties.maxPerStageDescriptorInlineUniformBlocks)
2181 			TCU_THROW(NotSupportedError, "Test require more per-stage inline uniform block bindings count. Provided " + de::toString(vulkan13properties.maxPerStageDescriptorInlineUniformBlocks));
2182 
2183 		if (m_params.bufferBindingCount > vulkan13properties.maxDescriptorSetInlineUniformBlocks)
2184 			TCU_THROW(NotSupportedError, "Test require more inline uniform block bindings among all stages. Provided " + de::toString(vulkan13properties.maxDescriptorSetInlineUniformBlocks));
2185 
2186 		if (m_params.bufferBindingCount > vulkan13properties.maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks)
2187 			TCU_THROW(NotSupportedError, "Test require more per-stage inline uniform block bindings count. Provided " + de::toString(vulkan13properties.maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks));
2188 
2189 		if (m_params.bufferBindingCount > vulkan13properties.maxDescriptorSetUpdateAfterBindInlineUniformBlocks)
2190 			TCU_THROW(NotSupportedError, "Test require more inline uniform block bindings among all stages. Provided " + de::toString(vulkan13properties.maxDescriptorSetUpdateAfterBindInlineUniformBlocks));
2191 	}
2192 
2193 	if (m_params.isAccelerationStructureObligatory())
2194 	{
2195 		context.requireDeviceFunctionality("VK_KHR_ray_query");
2196 	}
2197 
2198 	if (m_params.isRayTracing())
2199 	{
2200 		context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
2201 		context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
2202 	}
2203 }
2204 
2205 // The base class for all test case implementations.
2206 class DescriptorBufferTestInstance : public TestInstance
2207 {
2208 public:
2209 	DescriptorBufferTestInstance(
2210 		Context&							context,
2211 		const TestParams&					params,
2212 		const std::vector<SimpleBinding>&	simpleBindings);
2213 
2214 	tcu::TestStatus					iterate						() override;
2215 
2216 	void							createRayTracingPipeline	();
2217 	de::MovePtr<BufferWithMemory>	createShaderBindingTable	(const InstanceInterface&			vki,
2218 																 const DeviceInterface&				vkd,
2219 																 const VkDevice						device,
2220 																 const VkPhysicalDevice				physicalDevice,
2221 																 const VkPipeline					pipeline,
2222 																 Allocator&							allocator,
2223 																 de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
2224 																 const deUint32						group);
2225 	void							addRayTracingShader			(const VkShaderStageFlagBits		stage,
2226 																 const uint32_t						group);
2227 
2228 	void							createGraphicsPipeline		();
2229 	void							createDescriptorSetLayouts	();
2230 	void							createDescriptorBuffers		();
2231 
2232 	void							initializeBinding			(const DescriptorSetLayoutHolder&	dsl,
2233 																 deUint32							setIndex,
2234 																 Binding&							binding);
2235 
2236 	void							pushDescriptorSet			(VkCommandBuffer					cmdBuf,
2237 																 VkPipelineBindPoint				bindPoint,
2238 																 const DescriptorSetLayoutHolder&	dsl,
2239 																 deUint32							setIndex) const;
2240 
2241 	void							bindDescriptorBuffers		(VkCommandBuffer					cmdBuf,
2242 																 VkPipelineBindPoint				bindPoint) const;
2243 
2244 	void							createBufferForBinding		(ResourceHolder&					resources,
2245 																 VkDescriptorType					descriptorType,
2246 																 VkBufferCreateInfo					createInfo,
2247 																 bool								isResultBuffer) const;
2248 
2249 	void							createImageForBinding		(ResourceHolder&					resources,
2250 																 VkDescriptorType					descriptorType) const;
2251 
allocate(const VkMemoryRequirements & memReqs,const MemoryRequirement requirement,const void * pNext=nullptr) const2252 	MovePtr<Allocation>				allocate					(const VkMemoryRequirements&		memReqs,
2253 																 const MemoryRequirement			requirement,
2254 																 const void*						pNext = nullptr) const
2255 	{
2256 		return allocateExtended(
2257 			m_context.getInstanceInterface(),
2258 			*m_deviceInterface,
2259 			m_context.getPhysicalDevice(),
2260 			*m_device,
2261 			memReqs,
2262 			requirement,
2263 			pNext);
2264 	}
2265 
2266 	// Descriptor size is used to determine the stride of a descriptor array (for bindings with multiple descriptors).
2267 	VkDeviceSize					getDescriptorSize			(const Binding&						binding) const;
2268 
addDescriptorSetLayout()2269 	deUint32						addDescriptorSetLayout		()
2270 	{
2271 		m_descriptorSetLayouts.emplace_back(makeSharedUniquePtr<DescriptorSetLayoutHolder>());
2272 		return u32(m_descriptorSetLayouts.size()) - 1;
2273 	}
2274 
2275 	// The resources used by descriptors are tracked in a simple array and referenced by an index.
addResource()2276 	deUint32 addResource()
2277 	{
2278 		m_resources.emplace_back(makeSharedUniquePtr<ResourceHolder>());
2279 		return u32(m_resources.size()) - 1;
2280 	}
2281 
getOrCreateResource(Binding & binding,deUint32 arrayIndex)2282 	ResourceHolder& getOrCreateResource (Binding& binding, deUint32 arrayIndex)
2283 	{
2284 		if (binding.perBindingResourceIndex[arrayIndex] == INDEX_INVALID)
2285 		{
2286 			binding.perBindingResourceIndex[arrayIndex] = addResource();
2287 		}
2288 
2289 		ResourceHolder& result = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]);
2290 
2291 		return result;
2292 	}
2293 
getShaderName(const VkShaderStageFlagBits stage) const2294 	const std::string				getShaderName				(const VkShaderStageFlagBits		stage) const
2295 	{
2296 		return toString(stage) + (m_params.isAccelerationStructure() && (m_params.stage == stage) ? "_as" : "");
2297 	}
2298 
getShaderBinary(const VkShaderStageFlagBits stage) const2299 	const ProgramBinary&			getShaderBinary				(const VkShaderStageFlagBits		stage) const
2300 	{
2301 		return m_context.getBinaryCollection().get(getShaderName(stage));
2302 	}
2303 
isCaptureDescriptor(VkDescriptorType type) const2304 	bool							isCaptureDescriptor			(VkDescriptorType					type) const
2305 	{
2306 		return (m_testIteration == 0) && m_params.isCaptureReplayDescriptor(type);
2307 	}
2308 
isReplayDescriptor(VkDescriptorType type) const2309 	bool							isReplayDescriptor			(VkDescriptorType					type) const
2310 	{
2311 		return (m_testIteration == 1) && m_params.isCaptureReplayDescriptor(type);
2312 	}
2313 
2314 	// Test cases using compute shaders always declare one binding with a result buffer.
getResultBuffer() const2315 	const BufferAlloc&				getResultBuffer				() const
2316 	{
2317 		DE_ASSERT(m_params.isCompute() || m_params.isRayTracing());
2318 
2319 		const deUint32 resultBufferIndex = getResultBufferIndex(m_simpleBindings);
2320 		DE_ASSERT(resultBufferIndex != INDEX_INVALID);
2321 		const auto& sb = m_simpleBindings[resultBufferIndex];
2322 
2323 		const auto binding = std::find_if(
2324 			(**m_descriptorSetLayouts[sb.set]).bindings.begin(),
2325 			(**m_descriptorSetLayouts[sb.set]).bindings.end(),
2326 			[&sb](const Binding& it){ return it.binding == sb.binding; });
2327 
2328 		DE_ASSERT(binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2329 
2330 		// There's only one result buffer at this binding
2331 		return (**m_resources[binding->perBindingResourceIndex[0]]).buffer;
2332 	}
2333 
2334 protected:
2335 	TestParams										m_params;
2336 	std::vector<SimpleBinding>						m_simpleBindings;
2337 
2338 	Move<VkDevice>									m_device;
2339 	MovePtr<DeviceDriver>							m_deviceInterface;
2340 	VkQueue											m_queue;
2341 	deUint32										m_queueFamilyIndex;
2342 	MovePtr<Allocator>								m_allocatorPtr;
2343 
2344 	VkPhysicalDeviceMemoryProperties				m_memoryProperties;
2345 	VkPhysicalDeviceDescriptorBufferFeaturesEXT		m_descriptorBufferFeatures;
2346 	VkPhysicalDeviceDescriptorBufferPropertiesEXT	m_descriptorBufferProperties;
2347 
2348 	Move<VkPipeline>								m_pipeline;
2349 	Move<VkPipelineLayout>							m_pipelineLayout;
2350 
2351 	// Optional, for graphics pipelines
2352 	Move<VkFramebuffer>								m_framebuffer;
2353 	Move<VkRenderPass>								m_renderPass;
2354 	VkRect2D										m_renderArea;
2355 	ImageAlloc										m_colorImage;
2356 	BufferAlloc										m_colorBuffer;			// for copying back to host visible memory
2357 
2358 	std::vector<DSLPtr>								m_descriptorSetLayouts;
2359 	std::vector<BufferAllocPtr>						m_descriptorBuffers;
2360 	BufferAlloc										m_descriptorStagingBuffer;
2361 
2362 	// Ray Tracing fields
2363 	deUint32										m_shaders;
2364 	deUint32										m_raygenShaderGroup;
2365 	deUint32										m_missShaderGroup;
2366 	deUint32										m_hitShaderGroup;
2367 	deUint32										m_callableShaderGroup;
2368 	deUint32										m_shaderGroupCount;
2369 
2370 	de::MovePtr<RayTracingPipeline>					m_rayTracingPipeline;
2371 
2372 	de::MovePtr<BufferWithMemory>					m_raygenShaderBindingTable;
2373 	de::MovePtr<BufferWithMemory>					m_hitShaderBindingTable;
2374 	de::MovePtr<BufferWithMemory>					m_missShaderBindingTable;
2375 	de::MovePtr<BufferWithMemory>					m_callableShaderBindingTable;
2376 
2377 	VkStridedDeviceAddressRegionKHR					m_raygenShaderBindingTableRegion;
2378 	VkStridedDeviceAddressRegionKHR					m_missShaderBindingTableRegion;
2379 	VkStridedDeviceAddressRegionKHR					m_hitShaderBindingTableRegion;
2380 	VkStridedDeviceAddressRegionKHR					m_callableShaderBindingTableRegion;
2381 
2382 	de::SharedPtr<BottomLevelAccelerationStructure>	m_bottomLevelAccelerationStructure;
2383 	de::SharedPtr<TopLevelAccelerationStructure>	m_topLevelAccelerationStructure;
2384 
2385 	// Common, but last
2386 	std::vector<ResourcePtr>						m_resources;			// various resources used to test the descriptors
2387 	deUint32										m_testIteration;		// for multi-pass tests such as capture/replay
2388 
2389 };
2390 
DescriptorBufferTestInstance(Context & context,const TestParams & params,const std::vector<SimpleBinding> & simpleBindings)2391 DescriptorBufferTestInstance::DescriptorBufferTestInstance(
2392 	Context&							context,
2393 	const TestParams&					params,
2394 	const std::vector<SimpleBinding>&	simpleBindings)
2395 	: TestInstance							(context)
2396 	, m_params								(params)
2397 	, m_simpleBindings						(simpleBindings)
2398 	, m_device								()
2399 	, m_deviceInterface						()
2400 	, m_queue								()
2401 	, m_queueFamilyIndex					()
2402 	, m_allocatorPtr						(DE_NULL)
2403 	, m_memoryProperties					()
2404 	, m_descriptorBufferFeatures			()
2405 	, m_descriptorBufferProperties			()
2406 	, m_pipeline							()
2407 	, m_pipelineLayout						()
2408 	, m_framebuffer							()
2409 	, m_renderPass							()
2410 	, m_renderArea							(makeRect2D(0, 0, 4, 1))
2411 	, m_colorImage							()
2412 	, m_colorBuffer							()
2413 	, m_descriptorSetLayouts				()
2414 	, m_descriptorBuffers					()
2415 	, m_descriptorStagingBuffer				()
2416 	, m_shaders								(0)
2417 	, m_raygenShaderGroup					(~0u)
2418 	, m_missShaderGroup						(~0u)
2419 	, m_hitShaderGroup						(~0u)
2420 	, m_callableShaderGroup					(~0u)
2421 	, m_shaderGroupCount					(0)
2422 	, m_rayTracingPipeline					(DE_NULL)
2423 	, m_raygenShaderBindingTable			()
2424 	, m_hitShaderBindingTable				()
2425 	, m_missShaderBindingTable				()
2426 	, m_callableShaderBindingTable			()
2427 	, m_raygenShaderBindingTableRegion		()
2428 	, m_missShaderBindingTableRegion		()
2429 	, m_hitShaderBindingTableRegion			()
2430 	, m_callableShaderBindingTableRegion	()
2431 	, m_bottomLevelAccelerationStructure	()
2432 	, m_topLevelAccelerationStructure		()
2433 	, m_resources()
2434 	, m_testIteration(0)
2435 {
2436 	// Need to create a new device because:
2437 	// - We want to test graphics and compute queues,
2438 	// - We must exclude VK_AMD_shader_fragment_mask from the enabled extensions.
2439 
2440 	if (m_params.isAccelerationStructure() && m_params.isAccelerationStructureOptional())
2441 	{
2442 		if (!m_context.getRayQueryFeatures().rayQuery)
2443 		{
2444 			// Disable testing of acceleration structures if they ray query is not supported
2445 			m_params.descriptor = VK_DESCRIPTOR_TYPE_MAX_ENUM;
2446 
2447 			// Replace acceleration structures with storage buffers
2448 			for (auto& simpleBinding : m_simpleBindings)
2449 				if ((simpleBinding.type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) && !simpleBinding.isRayTracingAS)
2450 					simpleBinding.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2451 		}
2452 		else
2453 		{
2454 			context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
2455 		}
2456 	}
2457 
2458 	if ((m_params.variant == TestVariant::MULTIPLE) ||
2459 		(m_params.variant == TestVariant::PUSH_DESCRIPTOR) ||
2460 		(m_params.variant == TestVariant::PUSH_TEMPLATE) ||
2461 		(m_params.variant == TestVariant::ROBUST_BUFFER_ACCESS) ||
2462 		(m_params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR))
2463 	{
2464 		const vk::VkPhysicalDeviceLimits&	limits									= context.getDeviceProperties().limits;
2465 		deUint32							maxPerStageDescriptorSamplers			= 0; // VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
2466 		deUint32							maxPerStageDescriptorUniformBuffers		= 0; // VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
2467 		deUint32							maxPerStageDescriptorStorageBuffers		= 0; // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
2468 		deUint32							maxPerStageDescriptorSampledImages		= 0; // VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, or VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
2469 		deUint32							maxPerStageDescriptorStorageImages		= 0; // VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, or VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
2470 		deUint32							maxPerStageDescriptorInputAttachments	= 0; // VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
2471 
2472 		for (const auto& simpleBinding : m_simpleBindings)
2473 		{
2474 			switch (simpleBinding.type)
2475 			{
2476 				case VK_DESCRIPTOR_TYPE_SAMPLER:
2477 					maxPerStageDescriptorSamplers += simpleBinding.count;
2478 					break;
2479 				case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2480 					maxPerStageDescriptorSamplers += simpleBinding.count;
2481 					maxPerStageDescriptorSampledImages += simpleBinding.count;
2482 					break;
2483 				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2484 					maxPerStageDescriptorUniformBuffers += simpleBinding.count;
2485 					break;
2486 				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2487 					maxPerStageDescriptorStorageBuffers += simpleBinding.count;
2488 					break;
2489 				case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2490 					maxPerStageDescriptorSampledImages += simpleBinding.count;
2491 					break;
2492 				case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2493 					maxPerStageDescriptorSampledImages += simpleBinding.count;
2494 					break;
2495 				case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2496 					maxPerStageDescriptorStorageImages += simpleBinding.count;
2497 					break;
2498 				case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2499 					maxPerStageDescriptorStorageImages += simpleBinding.count;
2500 					break;
2501 				case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2502 					maxPerStageDescriptorInputAttachments += simpleBinding.count;
2503 					break;
2504 				default:
2505 					break;
2506 			}
2507 		}
2508 
2509 #define VALIDATE_PER_STAGE_LIMIT(NAME) if (NAME > limits.NAME) TCU_THROW(NotSupportedError, std::string(#NAME) + " " + de::toString(NAME) + " is greater than limit " + de::toString(limits.NAME));
2510 		VALIDATE_PER_STAGE_LIMIT(maxPerStageDescriptorSamplers);
2511 		VALIDATE_PER_STAGE_LIMIT(maxPerStageDescriptorUniformBuffers);
2512 		VALIDATE_PER_STAGE_LIMIT(maxPerStageDescriptorStorageBuffers);
2513 		VALIDATE_PER_STAGE_LIMIT(maxPerStageDescriptorSampledImages);
2514 		VALIDATE_PER_STAGE_LIMIT(maxPerStageDescriptorStorageImages);
2515 		VALIDATE_PER_STAGE_LIMIT(maxPerStageDescriptorInputAttachments);
2516 #undef VALIDATE_PER_STAGE_LIMIT
2517 	}
2518 
2519 
2520 	auto& inst			= context.getInstanceInterface();
2521 	auto  physDevice	= context.getPhysicalDevice();
2522 	auto queueProps		= getPhysicalDeviceQueueFamilyProperties(inst, physDevice);
2523 
2524 	m_queueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2525 
2526 	for (deUint32 i = 0; i < queueProps.size(); ++i)
2527 	{
2528 		if (m_params.queue == VK_QUEUE_GRAPHICS_BIT)
2529 		{
2530 			if ((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
2531 			{
2532 				m_queueFamilyIndex = i;
2533 
2534 				break;
2535 			}
2536 		}
2537 		else if (m_params.queue == VK_QUEUE_COMPUTE_BIT)
2538 		{
2539 			if (((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) &&
2540 				((queueProps[i].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0))
2541 			{
2542 				m_queueFamilyIndex = i;
2543 			}
2544 		}
2545 	}
2546 
2547 	if (m_queueFamilyIndex == VK_QUEUE_FAMILY_IGNORED)
2548 	{
2549 		TCU_THROW(NotSupportedError, "Queue not supported");
2550 	}
2551 
2552 	const float priority[1] = { 0.5f };
2553 
2554 	VkDeviceQueueCreateInfo queueInfo = initVulkanStructure();
2555 	queueInfo.queueFamilyIndex = m_queueFamilyIndex;
2556 	queueInfo.queueCount       = 1;
2557 	queueInfo.pQueuePriorities = priority;
2558 
2559 	VkPhysicalDeviceFeatures2							features2						= initVulkanStructure();
2560 	VkPhysicalDeviceDescriptorBufferFeaturesEXT			descriptorBufferFeatures		= initVulkanStructure();
2561 	VkPhysicalDeviceInlineUniformBlockFeaturesEXT		inlineUniformBlockFeatures		= initVulkanStructure();
2562 	VkPhysicalDeviceSynchronization2FeaturesKHR			synchronization2Features		= initVulkanStructure();
2563 	VkPhysicalDeviceRobustness2FeaturesEXT				robustness2Features				= initVulkanStructure();
2564 	VkPhysicalDeviceCustomBorderColorFeaturesEXT		customBorderColorFeatures		= initVulkanStructure();
2565 	VkPhysicalDeviceAccelerationStructureFeaturesKHR	accelerationStructureFeatures	= initVulkanStructure();
2566 	VkPhysicalDeviceRayQueryFeaturesKHR					rayQueryFeatures				= initVulkanStructure();
2567 	VkPhysicalDeviceRayTracingPipelineFeaturesKHR		rayTracingPipelineFeatures		= initVulkanStructure();
2568 	VkPhysicalDeviceBufferDeviceAddressFeatures			bufferDeviceAddressFeatures		= initVulkanStructure();
2569 	VkPhysicalDeviceMaintenance4Features				maintenance4Features			= initVulkanStructure();
2570 
2571 	void** nextPtr = &features2.pNext;
2572 	addToChainVulkanStructure(&nextPtr, synchronization2Features);
2573 	addToChainVulkanStructure(&nextPtr, descriptorBufferFeatures);
2574 	addToChainVulkanStructure(&nextPtr, bufferDeviceAddressFeatures);
2575 	addToChainVulkanStructure(&nextPtr, maintenance4Features);
2576 
2577 	// NOTE: VK_AMD_shader_fragment_mask must not be enabled
2578 	std::vector<const char*> extensions;
2579 	extensions.push_back("VK_EXT_descriptor_buffer");
2580 	extensions.push_back("VK_KHR_buffer_device_address");
2581 	extensions.push_back("VK_KHR_synchronization2");
2582 	extensions.push_back("VK_EXT_descriptor_indexing");
2583 	extensions.push_back("VK_KHR_maintenance4");
2584 
2585 	if ((m_params.descriptor == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) ||
2586 		(m_params.variant == TestVariant::MULTIPLE) ||
2587 		m_params.isPushDescriptorTest())
2588 	{
2589 		extensions.push_back("VK_EXT_inline_uniform_block");
2590 		addToChainVulkanStructure(&nextPtr, inlineUniformBlockFeatures);
2591 
2592 		if (m_params.isPushDescriptorTest())
2593 			extensions.push_back("VK_KHR_push_descriptor");
2594 	}
2595 	else if (m_params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR ||
2596 			 m_params.variant == TestVariant::ROBUST_BUFFER_ACCESS)
2597 	{
2598 		if (context.isDeviceFunctionalitySupported("VK_EXT_robustness2"))
2599 		{
2600 			extensions.push_back("VK_EXT_robustness2");
2601 			addToChainVulkanStructure(&nextPtr, robustness2Features);
2602 		}
2603 	}
2604 	else if (m_params.subcase == SubCase::CAPTURE_REPLAY_CUSTOM_BORDER_COLOR)
2605 	{
2606 		extensions.push_back("VK_EXT_custom_border_color");
2607 		addToChainVulkanStructure(&nextPtr, customBorderColorFeatures);
2608 	}
2609 
2610 	if (m_params.isAccelerationStructure() || m_params.isRayTracing())
2611 	{
2612 		extensions.push_back("VK_KHR_acceleration_structure");
2613 		addToChainVulkanStructure(&nextPtr, accelerationStructureFeatures);
2614 		extensions.push_back("VK_KHR_spirv_1_4");
2615 		extensions.push_back("VK_KHR_deferred_host_operations");
2616 
2617 		if (m_params.isAccelerationStructure())
2618 		{
2619 			extensions.push_back("VK_KHR_ray_query");
2620 			addToChainVulkanStructure(&nextPtr, rayQueryFeatures);
2621 			extensions.push_back("VK_KHR_deferred_host_operations");
2622 		}
2623 
2624 		if (m_params.isRayTracing())
2625 		{
2626 			extensions.push_back("VK_KHR_ray_tracing_pipeline");
2627 			addToChainVulkanStructure(&nextPtr, rayTracingPipelineFeatures);
2628 		}
2629 	}
2630 
2631 	context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2632 
2633 	if (m_params.variant != TestVariant::ROBUST_BUFFER_ACCESS)
2634 	{
2635 		features2.features.robustBufferAccess   = VK_FALSE;
2636 		robustness2Features.robustBufferAccess2 = VK_FALSE;
2637 		robustness2Features.robustImageAccess2  = VK_FALSE;
2638 	}
2639 
2640 	if (m_params.variant != TestVariant::ROBUST_NULL_DESCRIPTOR)
2641 	{
2642 		robustness2Features.nullDescriptor = VK_FALSE;
2643 	}
2644 
2645 	if (!m_params.isPushDescriptorTest())
2646 	{
2647 		descriptorBufferFeatures.descriptorBufferPushDescriptors = VK_FALSE;
2648 	}
2649 
2650 	if (!maintenance4Features.maintenance4)
2651 		TCU_THROW(NotSupportedError, "Execution mode LocalSizeId is used, maintenance4 required");
2652 
2653 	if (m_params.isAccelerationStructure() || m_params.isRayTracing())
2654 	{
2655 		if (!accelerationStructureFeatures.accelerationStructure)
2656 			TCU_THROW(NotSupportedError, "Require accelerationStructureFeatures.accelerationStructure");
2657 
2658 		if (m_params.isCaptureReplayDescriptor(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR))
2659 		{
2660 			if (!accelerationStructureFeatures.accelerationStructureCaptureReplay)
2661 				TCU_THROW(NotSupportedError, "Require accelerationStructureFeatures.accelerationStructureCaptureReplay");
2662 		}
2663 
2664 		if (m_params.isAccelerationStructure())
2665 		{
2666 			if (!rayQueryFeatures.rayQuery)
2667 				TCU_THROW(NotSupportedError, "Require rayQueryFeatures.rayQuery");
2668 		}
2669 
2670 		if (m_params.isRayTracing())
2671 		{
2672 			if (!rayTracingPipelineFeatures.rayTracingPipeline)
2673 				TCU_THROW(NotSupportedError, "Require rayTracingPipelineFeatures.rayTracingPipeline");
2674 
2675 			if (m_params.isCaptureReplayDescriptor(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR))
2676 			{
2677 				if (!rayTracingPipelineFeatures.rayTracingPipelineShaderGroupHandleCaptureReplay)
2678 					TCU_THROW(NotSupportedError, "Require rayTracingPipelineFeatures.rayTracingPipelineShaderGroupHandleCaptureReplay");
2679 			}
2680 		}
2681 	}
2682 
2683 	// Should be enabled by default
2684 	DE_ASSERT(descriptorBufferFeatures.descriptorBuffer);
2685 	DE_ASSERT(synchronization2Features.synchronization2);
2686 
2687 	if (m_params.variant == TestVariant::MULTIPLE || m_params.isPushDescriptorTest())
2688 	{
2689 		// TODO: Currently these tests assume the feature is available and there's no easy way to make it optional.
2690 		// Rather than returning NotSupported, this should be reworked if many implementations have this limitation.
2691 		DE_ASSERT(inlineUniformBlockFeatures.inlineUniformBlock);
2692 	}
2693 	else if (m_params.subcase == SubCase::CAPTURE_REPLAY_CUSTOM_BORDER_COLOR)
2694 	{
2695 		DE_ASSERT(customBorderColorFeatures.customBorderColors);
2696 	}
2697 
2698 	m_descriptorBufferFeatures		 = descriptorBufferFeatures;
2699 	m_descriptorBufferFeatures.pNext = nullptr;
2700 
2701 	m_descriptorBufferProperties	   = *findStructure<VkPhysicalDeviceDescriptorBufferPropertiesEXT>(&context.getDeviceProperties2());
2702 	m_descriptorBufferProperties.pNext = nullptr;
2703 
2704 	VkDeviceCreateInfo createInfo = initVulkanStructure(&features2);
2705 	createInfo.pEnabledFeatures		   = DE_NULL;
2706 	createInfo.enabledExtensionCount   = u32(extensions.size());
2707 	createInfo.ppEnabledExtensionNames = extensions.data();
2708 	createInfo.queueCreateInfoCount    = 1;
2709 	createInfo.pQueueCreateInfos       = &queueInfo;
2710 
2711 	m_device = createCustomDevice(
2712 		false,
2713 		context.getPlatformInterface(),
2714 		context.getInstance(),
2715 		inst,
2716 		physDevice,
2717 		&createInfo);
2718 
2719 	context.getDeviceInterface().getDeviceQueue(
2720 		*m_device,
2721 		m_queueFamilyIndex,
2722 		0,
2723 		&m_queue);
2724 
2725 	m_deviceInterface = newMovePtr<DeviceDriver>(context.getPlatformInterface(), context.getInstance(), *m_device);
2726 
2727 	m_memoryProperties = vk::getPhysicalDeviceMemoryProperties(inst, physDevice);
2728 
2729 	m_allocatorPtr = de::MovePtr<Allocator>(new SimpleAllocator(*m_deviceInterface, *m_device, m_memoryProperties));
2730 }
2731 
getDescriptorSize(const Binding & binding) const2732 VkDeviceSize DescriptorBufferTestInstance::getDescriptorSize(const Binding& binding) const
2733 {
2734 	const auto isRobustBufferAccess = (m_params.variant == TestVariant::ROBUST_BUFFER_ACCESS);
2735 
2736 	std::size_t size = 0u;
2737 
2738 	switch (binding.descriptorType) {
2739 	case VK_DESCRIPTOR_TYPE_SAMPLER:
2740 		size = m_descriptorBufferProperties.samplerDescriptorSize;
2741 		break;
2742 
2743 	case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2744 		size = m_descriptorBufferProperties.combinedImageSamplerDescriptorSize;
2745 		break;
2746 
2747 	case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2748 		size = m_descriptorBufferProperties.sampledImageDescriptorSize;
2749 		break;
2750 
2751 	case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2752 		size = m_descriptorBufferProperties.storageImageDescriptorSize;
2753 		break;
2754 
2755 	case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2756 		size = isRobustBufferAccess ? m_descriptorBufferProperties.robustUniformTexelBufferDescriptorSize
2757 									: m_descriptorBufferProperties.uniformTexelBufferDescriptorSize;
2758 		break;
2759 
2760 	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2761 		size = isRobustBufferAccess ? m_descriptorBufferProperties.robustStorageTexelBufferDescriptorSize
2762 									: m_descriptorBufferProperties.storageTexelBufferDescriptorSize;
2763 		break;
2764 
2765 	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2766 		size = isRobustBufferAccess ? m_descriptorBufferProperties.robustUniformBufferDescriptorSize
2767 									: m_descriptorBufferProperties.uniformBufferDescriptorSize;
2768 		break;
2769 
2770 	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2771 		size = isRobustBufferAccess ? m_descriptorBufferProperties.robustStorageBufferDescriptorSize
2772 									: m_descriptorBufferProperties.storageBufferDescriptorSize;
2773 		break;
2774 
2775 	case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2776 		size = m_descriptorBufferProperties.inputAttachmentDescriptorSize;
2777 		break;
2778 
2779 	case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
2780 		size = m_descriptorBufferProperties.accelerationStructureDescriptorSize;
2781 		break;
2782 
2783 	case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
2784 		// Inline uniform block has no associated size. This is OK, because it can't be arrayed.
2785 		break;
2786 
2787 	default:
2788 		DE_ASSERT(0);
2789 		break;
2790 	}
2791 
2792 	return size;
2793 }
2794 
createDescriptorSetLayouts()2795 void DescriptorBufferTestInstance::createDescriptorSetLayouts()
2796 {
2797 	for (auto& dslPtr : m_descriptorSetLayouts)
2798 	{
2799 		auto& dsl = **dslPtr;
2800 
2801 		DE_ASSERT(!dsl.bindings.empty());
2802 
2803 		const auto bindingsCopy = getDescriptorSetLayoutBindings(dsl.bindings);
2804 
2805 		VkDescriptorSetLayoutCreateInfo createInfo = initVulkanStructure();
2806 		createInfo.bindingCount = u32(bindingsCopy.size());
2807 		createInfo.pBindings    = bindingsCopy.data();
2808 		createInfo.flags		= VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
2809 
2810 		if (dsl.hasEmbeddedImmutableSamplers)
2811 		{
2812 			createInfo.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT;
2813 		}
2814 		else if (dsl.usePushDescriptors)
2815 		{
2816 			createInfo.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
2817 		}
2818 
2819 		dsl.layout = createDescriptorSetLayout(*m_deviceInterface, *m_device, &createInfo);
2820 
2821 		m_deviceInterface->getDescriptorSetLayoutSizeEXT(*m_device, *dsl.layout, &dsl.sizeOfLayout);
2822 
2823 		for (auto& binding : dsl.bindings)
2824 		{
2825 			m_deviceInterface->getDescriptorSetLayoutBindingOffsetEXT(
2826 				*m_device,
2827 				*dsl.layout,
2828 				binding.binding,
2829 				&binding.offset);
2830 		}
2831 	}
2832 }
2833 
2834 // The test may create a variable number of descriptor buffers, based on the parameters.
2835 //
createDescriptorBuffers()2836 void DescriptorBufferTestInstance::createDescriptorBuffers()
2837 {
2838 	DE_ASSERT(m_descriptorBuffers.empty());
2839 
2840 	const deUint8	bufferInitialMemory					= 0xcc;			// descriptor buffer memory is initially set to this
2841 	bool			allocateStagingBuffer				= false;		// determined after descriptors are created
2842 	VkDeviceSize	stagingBufferDescriptorSetOffset	= 0;
2843 	const deUint32	setsPerBuffer						= m_params.subcase == SubCase::SINGLE_BUFFER
2844 														? m_params.bufferBindingCount + 1
2845 														: m_params.setsPerBuffer;
2846 
2847 	// Data tracked per buffer creation
2848 	struct
2849 	{
2850 		deUint32			firstSet;
2851 		deUint32			numSets;
2852 		VkBufferUsageFlags	usage;
2853 		VkDeviceSize		setOffset;
2854 	} currentBuffer;
2855 
2856 	currentBuffer = {};
2857 
2858 	for (deUint32 setIndex = 0; setIndex < u32(m_descriptorSetLayouts.size()); ++setIndex)
2859 	{
2860 		auto& dsl = **m_descriptorSetLayouts[setIndex];
2861 
2862 		if (dsl.hasEmbeddedImmutableSamplers || (dsl.usePushDescriptors && m_descriptorBufferProperties.bufferlessPushDescriptors && m_params.subcase != SubCase::SINGLE_BUFFER))
2863 		{
2864 			// Embedded immutable samplers aren't backed by a descriptor buffer.
2865 			// Same goes for the set used with push descriptors.
2866 			// Push descriptors might require buffer. If so, don't skip creation of buffer.
2867 
2868 			// We musn't have started adding sets to the next buffer yet.
2869 			DE_ASSERT(currentBuffer.numSets == 0);
2870 			++currentBuffer.firstSet;
2871 
2872 			continue;
2873 		}
2874 
2875 		// Required for binding
2876 		currentBuffer.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
2877 
2878 		for (const auto& binding : dsl.bindings)
2879 		{
2880 			if (binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
2881 			{
2882 				currentBuffer.usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
2883 			}
2884 			else if (binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
2885 			{
2886 				currentBuffer.usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT |
2887 									   VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT;
2888 			}
2889 			else
2890 			{
2891 				currentBuffer.usage |= VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT;
2892 			}
2893 		}
2894 
2895 		if (!m_descriptorBufferProperties.bufferlessPushDescriptors && dsl.usePushDescriptors)
2896 		{
2897 			currentBuffer.usage |= VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT;
2898 		}
2899 
2900 		// Allow descriptor set layout to be size of zero bytes
2901 		if (dsl.sizeOfLayout != 0)
2902 		{
2903 			// Assign this descriptor set to a new buffer
2904 			dsl.bufferIndex  = u32(m_descriptorBuffers.size());
2905 			dsl.bufferOffset = currentBuffer.setOffset;
2906 		}
2907 
2908 		currentBuffer.numSets   += 1;
2909 		currentBuffer.setOffset += deAlignSize(
2910 			static_cast<std::size_t>(dsl.sizeOfLayout),
2911 			static_cast<std::size_t>(m_descriptorBufferProperties.descriptorBufferOffsetAlignment));
2912 
2913 		VkMemoryAllocateFlagsInfo					allocFlagsInfo						= initVulkanStructure();
2914 		allocFlagsInfo.flags |= VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
2915 
2916 		// We've reached the limit of sets for this descriptor buffer.
2917 		if (currentBuffer.numSets == setsPerBuffer)
2918 		{
2919 			vk::VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(currentBuffer.setOffset, currentBuffer.usage);
2920 
2921 			if (bufferCreateInfo.size != 0)
2922 			{
2923 				m_descriptorBuffers.emplace_back(new BufferAlloc());
2924 				auto& bufferAlloc = *m_descriptorBuffers.back();
2925 
2926 				bufferAlloc.buffer = vk::createBuffer(*m_deviceInterface, *m_device, &bufferCreateInfo);
2927 				bufferAlloc.size = bufferCreateInfo.size;
2928 				bufferAlloc.usage = bufferCreateInfo.usage;
2929 
2930 				auto bufferMemReqs = getBufferMemoryRequirements(*m_deviceInterface, *m_device, *bufferAlloc.buffer);
2931 				bool useStagedUpload = false;	// write directly to device-local memory, if possible
2932 
2933 				if (DEBUG_FORCE_STAGED_UPLOAD)
2934 				{
2935 					useStagedUpload = true;
2936 				}
2937 				else if (DEBUG_MIX_DIRECT_AND_STAGED_UPLOAD)
2938 				{
2939 					// To avoid adding yet another test case permutation (which may be redundant on some implementations),
2940 					// we are going to always test a mix of direct and staged uploads.
2941 					useStagedUpload = ((dsl.bufferIndex % 2) == 1);
2942 				}
2943 
2944 				if (!useStagedUpload)
2945 				{
2946 					auto memReqs = MemoryRequirement::Local | MemoryRequirement::HostVisible;
2947 					auto compatMask = bufferMemReqs.memoryTypeBits & getCompatibleMemoryTypes(m_memoryProperties, memReqs);
2948 
2949 					if (compatMask != 0)
2950 					{
2951 						bufferAlloc.alloc = allocate(bufferMemReqs, memReqs, &allocFlagsInfo);
2952 					}
2953 					else
2954 					{
2955 						// No suitable memory type, fall back to a staged upload
2956 						useStagedUpload = true;
2957 					}
2958 				}
2959 
2960 				if (useStagedUpload)
2961 				{
2962 					DE_ASSERT(!bufferAlloc.alloc);
2963 
2964 					if ((bufferAlloc.usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT) == 0)
2965 					{
2966 						bufferAlloc.buffer = Move<VkBuffer>();
2967 						bufferAlloc.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2968 
2969 						bufferCreateInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2970 
2971 						bufferAlloc.buffer = vk::createBuffer(*m_deviceInterface, *m_device, &bufferCreateInfo);
2972 
2973 						bufferMemReqs = getBufferMemoryRequirements(*m_deviceInterface, *m_device, *bufferAlloc.buffer);
2974 					}
2975 
2976 					bufferAlloc.alloc = allocate(bufferMemReqs, MemoryRequirement::Local, &allocFlagsInfo);
2977 					allocateStagingBuffer = true;
2978 
2979 					// Update staging buffer offsets for all sets in this buffer
2980 					for (deUint32 i = currentBuffer.firstSet; i < currentBuffer.firstSet + currentBuffer.numSets; ++i)
2981 					{
2982 						(**m_descriptorSetLayouts[i]).stagingBufferOffset = stagingBufferDescriptorSetOffset;
2983 						stagingBufferDescriptorSetOffset += (**m_descriptorSetLayouts[i]).sizeOfLayout;
2984 					}
2985 				}
2986 
2987 				VK_CHECK(m_deviceInterface->bindBufferMemory(
2988 					*m_device,
2989 					*bufferAlloc.buffer,
2990 					bufferAlloc.alloc->getMemory(),
2991 					bufferAlloc.alloc->getOffset()));
2992 
2993 				bufferAlloc.loadDeviceAddress(*m_deviceInterface, *m_device);
2994 
2995 				if (!useStagedUpload)
2996 				{
2997 					// Clear the descriptor buffer memory to ensure there can be no random data there.
2998 					deMemset(
2999 						bufferAlloc.alloc->getHostPtr(),
3000 						bufferInitialMemory,
3001 						static_cast<std::size_t>(bufferAlloc.size));
3002 				}
3003 			}
3004 
3005 			// Start with a new buffer
3006 			currentBuffer = {};
3007 			currentBuffer.firstSet = setIndex + 1;
3008 		}
3009 	}
3010 
3011 	if (allocateStagingBuffer)
3012 	{
3013 		DE_ASSERT(!m_descriptorStagingBuffer.alloc);
3014 
3015 		auto bufferCreateInfo = makeBufferCreateInfo(stagingBufferDescriptorSetOffset, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
3016 
3017 		m_descriptorStagingBuffer.buffer = vk::createBuffer(*m_deviceInterface, *m_device, &bufferCreateInfo);
3018 		m_descriptorStagingBuffer.size = bufferCreateInfo.size;
3019 
3020 		auto bufferMemReqs = getBufferMemoryRequirements(*m_deviceInterface, *m_device, *m_descriptorStagingBuffer.buffer);
3021 
3022 		m_descriptorStagingBuffer.alloc = allocate(bufferMemReqs, MemoryRequirement::HostVisible);
3023 
3024 		VK_CHECK(m_deviceInterface->bindBufferMemory(
3025 			*m_device,
3026 			*m_descriptorStagingBuffer.buffer,
3027 			m_descriptorStagingBuffer.alloc->getMemory(),
3028 			m_descriptorStagingBuffer.alloc->getOffset()));
3029 
3030 		// Clear the descriptor buffer memory to ensure there can be no random data there.
3031 		deMemset(
3032 			m_descriptorStagingBuffer.alloc->getHostPtr(),
3033 			bufferInitialMemory,
3034 			static_cast<std::size_t>(m_descriptorStagingBuffer.size));
3035 	}
3036 }
3037 
bindDescriptorBuffers(VkCommandBuffer cmdBuf,VkPipelineBindPoint bindPoint) const3038 void DescriptorBufferTestInstance::bindDescriptorBuffers(VkCommandBuffer cmdBuf, VkPipelineBindPoint bindPoint) const
3039 {
3040 	std::vector<deUint32>									bufferIndices;
3041 	std::vector<VkDeviceSize>								bufferOffsets;
3042 	std::vector<VkDescriptorBufferBindingInfoEXT>			bufferBindingInfos;
3043 	VkDescriptorBufferBindingPushDescriptorBufferHandleEXT	bufferBindingPushDescriptorBufferHandleEXT = initVulkanStructure();
3044 
3045 	deUint32 firstSet = 0;
3046 
3047 	if (m_params.variant == TestVariant::EMBEDDED_IMMUTABLE_SAMPLERS)
3048 	{
3049 		// These sampler sets are ordered first, so we can bind them now and increment the firstSet index.
3050 		for (deUint32 setIndex = firstSet; setIndex < u32(m_descriptorSetLayouts.size()); ++setIndex)
3051 		{
3052 			const auto& dsl = **m_descriptorSetLayouts[setIndex];
3053 
3054 			if (dsl.hasEmbeddedImmutableSamplers)
3055 			{
3056 				m_deviceInterface->cmdBindDescriptorBufferEmbeddedSamplersEXT(
3057 					cmdBuf,
3058 					bindPoint,
3059 					*m_pipelineLayout,
3060 					setIndex);
3061 
3062 				// No gaps between sets.
3063 				DE_ASSERT(firstSet == setIndex);
3064 
3065 				firstSet = setIndex + 1;
3066 			}
3067 		}
3068 	}
3069 
3070 	for (const auto& buffer : m_descriptorBuffers)
3071 	{
3072 		VkDescriptorBufferBindingInfoEXT info = initVulkanStructure();
3073 
3074 		info.address = buffer->deviceAddress;
3075 		info.usage   = buffer->usage;
3076 
3077 		if (!m_descriptorBufferProperties.bufferlessPushDescriptors && (buffer->usage & VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT) != 0)
3078 		{
3079 			info.pNext = &bufferBindingPushDescriptorBufferHandleEXT;
3080 
3081 			// Make sure there is only one such buffer
3082 			DE_ASSERT(bufferBindingPushDescriptorBufferHandleEXT.buffer == DE_NULL);
3083 
3084 			bufferBindingPushDescriptorBufferHandleEXT.buffer = *buffer->buffer;
3085 
3086 			DE_ASSERT(bufferBindingPushDescriptorBufferHandleEXT.buffer != DE_NULL);
3087 		}
3088 
3089 		bufferBindingInfos.emplace_back(info);
3090 	}
3091 
3092 	if (bufferBindingInfos.size() != 0u)
3093 	{
3094 		m_deviceInterface->cmdBindDescriptorBuffersEXT(
3095 			cmdBuf,
3096 			u32(bufferBindingInfos.size()),
3097 			bufferBindingInfos.data());
3098 	}
3099 
3100 	// Next, set the offsets for the bound buffers.
3101 
3102 	for (deUint32 setIndex = firstSet; setIndex < u32(m_descriptorSetLayouts.size()); ++setIndex)
3103 	{
3104 		const auto& dsl		   = **m_descriptorSetLayouts[setIndex];
3105 		const bool	isBoundSet = (dsl.bufferIndex != INDEX_INVALID);
3106 		const bool  isLastSet  = ((setIndex + 1) == u32(m_descriptorSetLayouts.size()));
3107 
3108 		if (isBoundSet)
3109 		{
3110 			bufferIndices.emplace_back(dsl.bufferIndex);
3111 			bufferOffsets.emplace_back(dsl.bufferOffset);
3112 		}
3113 
3114 		if ((!isBoundSet || isLastSet) && !bufferIndices.empty())
3115 		{
3116 			m_deviceInterface->cmdSetDescriptorBufferOffsetsEXT(
3117 				cmdBuf,
3118 				bindPoint,
3119 				*m_pipelineLayout,
3120 				firstSet,
3121 				u32(bufferIndices.size()),
3122 				bufferIndices.data(),
3123 				bufferOffsets.data());
3124 
3125 			bufferIndices.clear();
3126 			bufferOffsets.clear();
3127 
3128 			firstSet = setIndex + 1;
3129 		}
3130 		else if (!isBoundSet)
3131 		{
3132 			// Push descriptor sets will have no buffer backing. Skip this set.
3133 			++firstSet;
3134 		}
3135 	}
3136 }
3137 
makeShaderStageCreateInfo(VkShaderStageFlagBits stage,VkShaderModule shaderModule)3138 VkPipelineShaderStageCreateInfo makeShaderStageCreateInfo(VkShaderStageFlagBits stage, VkShaderModule shaderModule)
3139 {
3140 	VkPipelineShaderStageCreateInfo createInfo = initVulkanStructure();
3141 	createInfo.stage				= stage;
3142 	createInfo.module				= shaderModule;
3143 	createInfo.pName				= "main";
3144 	createInfo.pSpecializationInfo	= nullptr;
3145 	return createInfo;
3146 }
3147 
createShaderBindingTable(const InstanceInterface & vki,const DeviceInterface & vkd,const VkDevice device,const VkPhysicalDevice physicalDevice,const VkPipeline pipeline,Allocator & allocator,de::MovePtr<RayTracingPipeline> & rayTracingPipeline,const deUint32 group)3148 de::MovePtr<BufferWithMemory> DescriptorBufferTestInstance::createShaderBindingTable (const InstanceInterface&			vki,
3149 																					  const DeviceInterface&			vkd,
3150 																					  const VkDevice					device,
3151 																					  const VkPhysicalDevice			physicalDevice,
3152 																					  const VkPipeline					pipeline,
3153 																					  Allocator&						allocator,
3154 																					  de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
3155 																					  const deUint32					group)
3156 {
3157 	de::MovePtr<BufferWithMemory>	shaderBindingTable;
3158 
3159 	if (group < m_shaderGroupCount)
3160 	{
3161 		const deUint32	shaderGroupHandleSize		= getShaderGroupHandleSize(vki, physicalDevice);
3162 		const deUint32	shaderGroupBaseAlignment	= getShaderGroupBaseAlignment(vki, physicalDevice);
3163 
3164 		shaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, group, 1u);
3165 	}
3166 
3167 	return shaderBindingTable;
3168 }
3169 
createRayTracingPipeline()3170 void DescriptorBufferTestInstance::createRayTracingPipeline()
3171 {
3172 	const InstanceInterface&	vki						= m_context.getInstanceInterface();
3173 	const DeviceInterface&		vkd						= *m_deviceInterface;
3174 	const VkDevice				device					= *m_device;
3175 	const VkPhysicalDevice		physicalDevice			= m_context.getPhysicalDevice();
3176 	vk::BinaryCollection&		collection				= m_context.getBinaryCollection();
3177 	Allocator&					allocator				= *m_allocatorPtr;
3178 	const deUint32				shaderGroupHandleSize	= getShaderGroupHandleSize(vki, physicalDevice);
3179 	const VkShaderStageFlags	hitStages				= VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
3180 
3181 	m_shaderGroupCount = 0;
3182 
3183 	if (collection.contains(getShaderName(VK_SHADER_STAGE_RAYGEN_BIT_KHR)))			m_shaders |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
3184 	if (collection.contains(getShaderName(VK_SHADER_STAGE_ANY_HIT_BIT_KHR)))		m_shaders |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
3185 	if (collection.contains(getShaderName(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)))	m_shaders |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
3186 	if (collection.contains(getShaderName(VK_SHADER_STAGE_MISS_BIT_KHR)))			m_shaders |= VK_SHADER_STAGE_MISS_BIT_KHR;
3187 	if (collection.contains(getShaderName(VK_SHADER_STAGE_INTERSECTION_BIT_KHR)))	m_shaders |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
3188 	if (collection.contains(getShaderName(VK_SHADER_STAGE_CALLABLE_BIT_KHR)))		m_shaders |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
3189 
3190 	if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))
3191 		m_raygenShaderGroup		= m_shaderGroupCount++;
3192 
3193 	if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))
3194 		m_missShaderGroup		= m_shaderGroupCount++;
3195 
3196 	if (0 != (m_shaders & hitStages))
3197 		m_hitShaderGroup		= m_shaderGroupCount++;
3198 
3199 	if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))
3200 		m_callableShaderGroup	= m_shaderGroupCount++;
3201 
3202 	m_rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
3203 
3204 	m_rayTracingPipeline->setCreateFlags(VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT);
3205 
3206 	if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))			addRayTracingShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,			m_raygenShaderGroup);
3207 	if (0 != (m_shaders & VK_SHADER_STAGE_ANY_HIT_BIT_KHR))			addRayTracingShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR,		m_hitShaderGroup);
3208 	if (0 != (m_shaders & VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR))		addRayTracingShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	m_hitShaderGroup);
3209 	if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))			addRayTracingShader(VK_SHADER_STAGE_MISS_BIT_KHR,			m_missShaderGroup);
3210 	if (0 != (m_shaders & VK_SHADER_STAGE_INTERSECTION_BIT_KHR))	addRayTracingShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	m_hitShaderGroup);
3211 	if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))		addRayTracingShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR,		m_callableShaderGroup);
3212 
3213 	m_pipelineLayout					= makePipelineLayout(vkd, device, getDescriptorSetLayouts(m_descriptorSetLayouts));
3214 	m_pipeline							= m_rayTracingPipeline->createPipeline(vkd, device, *m_pipelineLayout);
3215 
3216 	m_raygenShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_raygenShaderGroup);
3217 	m_missShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_missShaderGroup);
3218 	m_hitShaderBindingTable				= createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_hitShaderGroup);
3219 	m_callableShaderBindingTable		= createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_callableShaderGroup);
3220 
3221 	m_raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_raygenShaderBindingTable),		shaderGroupHandleSize);
3222 	m_missShaderBindingTableRegion		= makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_missShaderBindingTable),		shaderGroupHandleSize);
3223 	m_hitShaderBindingTableRegion		= makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_hitShaderBindingTable),			shaderGroupHandleSize);
3224 	m_callableShaderBindingTableRegion	= makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_callableShaderBindingTable),	shaderGroupHandleSize);
3225 }
3226 
addRayTracingShader(const VkShaderStageFlagBits stage,const uint32_t group)3227 void DescriptorBufferTestInstance::addRayTracingShader (const VkShaderStageFlagBits		stage,
3228 														const uint32_t					group)
3229 {
3230 	DE_ASSERT(m_rayTracingPipeline != DE_NULL);
3231 
3232 	m_rayTracingPipeline->addShader(stage, createShaderModule(*m_deviceInterface, *m_device, getShaderBinary(stage), 0), group);
3233 }
3234 
3235 // The graphics pipeline is very simple for this test.
3236 // The number of shader stages is configurable. There's no vertex input, a single triangle covers the entire viewport.
3237 // The color target uses R32_UINT format and is used to save the verifcation result.
3238 //
createGraphicsPipeline()3239 void DescriptorBufferTestInstance::createGraphicsPipeline()
3240 {
3241 	std::vector<VkImageView> framebufferAttachments;
3242 
3243 	{
3244 		m_colorImage.info = initVulkanStructure();
3245 		m_colorImage.info.flags					= 0;
3246 		m_colorImage.info.imageType				= VK_IMAGE_TYPE_2D;
3247 		m_colorImage.info.format				= VK_FORMAT_R32_UINT;
3248 		m_colorImage.info.extent.width			= m_renderArea.extent.width;
3249 		m_colorImage.info.extent.height			= m_renderArea.extent.height;
3250 		m_colorImage.info.extent.depth			= 1;
3251 		m_colorImage.info.mipLevels				= 1;
3252 		m_colorImage.info.arrayLayers			= 1;
3253 		m_colorImage.info.samples				= VK_SAMPLE_COUNT_1_BIT;
3254 		m_colorImage.info.tiling				= VK_IMAGE_TILING_OPTIMAL;
3255 		m_colorImage.info.usage					= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3256 		m_colorImage.info.sharingMode			= VK_SHARING_MODE_EXCLUSIVE;
3257 		m_colorImage.info.queueFamilyIndexCount	= 0;
3258 		m_colorImage.info.pQueueFamilyIndices	= nullptr;
3259 		m_colorImage.info.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
3260 
3261 		m_colorImage.image = createImage(*m_deviceInterface, *m_device, &m_colorImage.info);
3262 
3263 		auto memReqs = getImageMemoryRequirements(*m_deviceInterface, *m_device, *m_colorImage.image);
3264 		m_colorImage.sizeBytes = memReqs.size;
3265 		m_colorImage.alloc	   = allocate(memReqs, MemoryRequirement::Local);
3266 
3267 		VK_CHECK(m_deviceInterface->bindImageMemory(
3268 			*m_device,
3269 			*m_colorImage.image,
3270 			m_colorImage.alloc->getMemory(),
3271 			m_colorImage.alloc->getOffset()));
3272 	}
3273 	{
3274 		auto createInfo = makeBufferCreateInfo(
3275 			m_colorImage.sizeBytes,
3276 			VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3277 
3278 		m_colorBuffer.buffer = createBuffer(*m_deviceInterface, *m_device, &createInfo);
3279 
3280 		auto memReqs = getBufferMemoryRequirements(*m_deviceInterface, *m_device, *m_colorBuffer.buffer);
3281 
3282 		m_colorBuffer.alloc = allocate(memReqs, MemoryRequirement::HostVisible);
3283 		VK_CHECK(m_deviceInterface->bindBufferMemory(
3284 			*m_device,
3285 			*m_colorBuffer.buffer,
3286 			m_colorBuffer.alloc->getMemory(),
3287 			m_colorBuffer.alloc->getOffset()));
3288 	}
3289 	{
3290 		VkImageViewCreateInfo createInfo = initVulkanStructure();
3291 		createInfo.image			= *m_colorImage.image;
3292 		createInfo.viewType			= VK_IMAGE_VIEW_TYPE_2D;
3293 		createInfo.format			= m_colorImage.info.format;
3294 		createInfo.components		= ComponentMappingIdentity;
3295 		createInfo.subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
3296 
3297 		m_colorImage.imageView = createImageView(*m_deviceInterface, *m_device, &createInfo);
3298 	}
3299 
3300 	framebufferAttachments.push_back(*m_colorImage.imageView);
3301 
3302 	{
3303 		std::vector<VkAttachmentDescription> attachments;
3304 		std::vector<VkAttachmentReference>	 colorRefs;
3305 		std::vector<VkAttachmentReference>	 inputRefs;
3306 
3307 		{
3308 			VkAttachmentDescription colorAttachment {};
3309 			colorAttachment.format			= VK_FORMAT_R32_UINT;
3310 			colorAttachment.samples			= VK_SAMPLE_COUNT_1_BIT;
3311 			colorAttachment.loadOp			= VK_ATTACHMENT_LOAD_OP_CLEAR;
3312 			colorAttachment.storeOp			= VK_ATTACHMENT_STORE_OP_STORE;
3313 			colorAttachment.stencilLoadOp	= VK_ATTACHMENT_LOAD_OP_DONT_CARE;
3314 			colorAttachment.stencilStoreOp	= VK_ATTACHMENT_STORE_OP_DONT_CARE;
3315 			colorAttachment.initialLayout	= VK_IMAGE_LAYOUT_UNDEFINED;
3316 			colorAttachment.finalLayout		= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
3317 
3318 			colorRefs.emplace_back(makeAttachmentReference(u32(attachments.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
3319 			attachments.emplace_back(colorAttachment);
3320 		}
3321 
3322 		for (deUint32 setIndex = 0; setIndex < u32(m_descriptorSetLayouts.size()); ++setIndex)
3323 		{
3324 			const auto& dsl = **m_descriptorSetLayouts[setIndex];
3325 
3326 			for (deUint32 bindingIndex = 0; bindingIndex < u32(dsl.bindings.size()); ++bindingIndex)
3327 			{
3328 				const auto& binding = dsl.bindings[bindingIndex];
3329 
3330 				if (binding.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
3331 				{
3332 					for (deUint32 arrayIndex = 0; arrayIndex < binding.descriptorCount; ++arrayIndex)
3333 					{
3334 						VkAttachmentDescription inputAttachment {};
3335 						inputAttachment.format			= VK_FORMAT_R32_UINT;
3336 						inputAttachment.samples			= VK_SAMPLE_COUNT_1_BIT;
3337 						inputAttachment.loadOp			= VK_ATTACHMENT_LOAD_OP_LOAD;
3338 						inputAttachment.storeOp			= VK_ATTACHMENT_STORE_OP_DONT_CARE;
3339 						inputAttachment.stencilLoadOp	= VK_ATTACHMENT_LOAD_OP_DONT_CARE;
3340 						inputAttachment.stencilStoreOp	= VK_ATTACHMENT_STORE_OP_DONT_CARE;
3341 						inputAttachment.initialLayout	= VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
3342 						inputAttachment.finalLayout		= VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
3343 
3344 						inputRefs.emplace_back(makeAttachmentReference(u32(attachments.size()), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
3345 						attachments.emplace_back(inputAttachment);
3346 
3347 						const auto inputAttachmentResourceIndex = binding.perBindingResourceIndex[arrayIndex];
3348 						framebufferAttachments.push_back(*(**m_resources[inputAttachmentResourceIndex]).image.imageView);
3349 					}
3350 				}
3351 			}
3352 		}
3353 
3354 		VkSubpassDescription subpass {};
3355 		subpass.pipelineBindPoint		= VK_PIPELINE_BIND_POINT_GRAPHICS;
3356 		subpass.inputAttachmentCount	= u32(inputRefs.size());
3357 		subpass.pInputAttachments		= inputRefs.data();
3358 		subpass.colorAttachmentCount	= u32(colorRefs.size());
3359 		subpass.pColorAttachments		= colorRefs.data();
3360 		subpass.pResolveAttachments		= nullptr;
3361 		subpass.pDepthStencilAttachment	= nullptr;
3362 		subpass.preserveAttachmentCount	= 0;
3363 		subpass.pPreserveAttachments	= nullptr;
3364 
3365 		VkRenderPassCreateInfo createInfo = initVulkanStructure();
3366 		// No explicit dependencies
3367 		createInfo.attachmentCount	= u32(attachments.size());
3368 		createInfo.pAttachments		= attachments.data();
3369 		createInfo.subpassCount		= 1;
3370 		createInfo.pSubpasses		= &subpass;
3371 
3372 		m_renderPass = createRenderPass(*m_deviceInterface, *m_device, &createInfo);
3373 	}
3374 	{
3375 		VkFramebufferCreateInfo createInfo = initVulkanStructure();
3376 		createInfo.renderPass		= *m_renderPass;
3377 		createInfo.attachmentCount	= u32(framebufferAttachments.size());
3378 		createInfo.pAttachments		= framebufferAttachments.data();
3379 		createInfo.width			= m_renderArea.extent.width;
3380 		createInfo.height			= m_renderArea.extent.height;
3381 		createInfo.layers			= 1;
3382 
3383 		m_framebuffer = createFramebuffer(*m_deviceInterface, *m_device, &createInfo);
3384 	}
3385 
3386 	std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
3387 
3388 	Move<VkShaderModule> vertModule;
3389 	Move<VkShaderModule> tessControlModule;
3390 	Move<VkShaderModule> tessEvalModule;
3391 	Move<VkShaderModule> geomModule;
3392 	Move<VkShaderModule> fragModule;
3393 
3394 	vertModule = createShaderModule(*m_deviceInterface, *m_device, getShaderBinary(VK_SHADER_STAGE_VERTEX_BIT), 0u);
3395 	fragModule = createShaderModule(*m_deviceInterface, *m_device, getShaderBinary(VK_SHADER_STAGE_FRAGMENT_BIT), 0u);
3396 
3397 	shaderStages.emplace_back(makeShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, *vertModule));
3398 	shaderStages.emplace_back(makeShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, *fragModule));
3399 
3400 	if (m_params.isTessellation())
3401 	{
3402 		tessControlModule = createShaderModule(*m_deviceInterface, *m_device, getShaderBinary(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), 0u);
3403 		tessEvalModule	  = createShaderModule(*m_deviceInterface, *m_device, getShaderBinary(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), 0u);
3404 
3405 		shaderStages.emplace_back(makeShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, *tessControlModule));
3406 		shaderStages.emplace_back(makeShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, *tessEvalModule));
3407 	}
3408 	else if (m_params.isGeometry())
3409 	{
3410 		geomModule = createShaderModule(*m_deviceInterface, *m_device, getShaderBinary(VK_SHADER_STAGE_GEOMETRY_BIT), 0u);
3411 
3412 		shaderStages.emplace_back(makeShaderStageCreateInfo(VK_SHADER_STAGE_GEOMETRY_BIT, *geomModule));
3413 	}
3414 
3415 	VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
3416 	// No vertex input
3417 
3418 	VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = initVulkanStructure();
3419 	inputAssemblyState.topology = !!tessControlModule ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
3420 
3421 	VkPipelineTessellationStateCreateInfo tesselationState = initVulkanStructure();
3422 	tesselationState.patchControlPoints = 3;
3423 
3424 	VkViewport viewport = makeViewport(m_renderArea.extent);
3425 
3426 	VkPipelineViewportStateCreateInfo viewportState = initVulkanStructure();
3427 	viewportState.viewportCount = 1;
3428 	viewportState.pViewports	= &viewport;
3429 	viewportState.scissorCount	= 1;
3430 	viewportState.pScissors		= &m_renderArea;
3431 
3432 	VkPipelineRasterizationStateCreateInfo rasterizationState = initVulkanStructure();
3433     rasterizationState.depthClampEnable			= VK_FALSE;
3434     rasterizationState.rasterizerDiscardEnable  = VK_FALSE;
3435     rasterizationState.polygonMode				= VK_POLYGON_MODE_FILL;
3436     rasterizationState.cullMode					= VK_CULL_MODE_NONE;
3437     rasterizationState.frontFace				= VK_FRONT_FACE_COUNTER_CLOCKWISE;
3438     rasterizationState.depthBiasEnable			= VK_FALSE;
3439     rasterizationState.depthBiasConstantFactor	= 0.0f;
3440     rasterizationState.depthBiasClamp			= 0.0f;
3441     rasterizationState.depthBiasSlopeFactor		= 0.0f;
3442     rasterizationState.lineWidth				= 1.0f;
3443 
3444 	VkPipelineMultisampleStateCreateInfo multisampleState = initVulkanStructure();
3445 	// Everything else disabled/default
3446 	multisampleState.rasterizationSamples	= VK_SAMPLE_COUNT_1_BIT;
3447 
3448 	VkPipelineDepthStencilStateCreateInfo depthStencilState = initVulkanStructure();
3449 	// Everything else disabled/default
3450     depthStencilState.minDepthBounds = 0.0f;
3451     depthStencilState.maxDepthBounds = 1.0f;
3452 
3453 	VkPipelineColorBlendAttachmentState colorAttachment {};
3454 	// Everything else disabled/default
3455 	colorAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
3456 
3457 	VkPipelineColorBlendStateCreateInfo colorBlendState = initVulkanStructure();
3458 	// Everything else disabled/default
3459     colorBlendState.attachmentCount	= 1;
3460     colorBlendState.pAttachments	= &colorAttachment;
3461 
3462 	{
3463 		VkGraphicsPipelineCreateInfo createInfo = initVulkanStructure();
3464 		createInfo.stageCount			= u32(shaderStages.size());
3465 		createInfo.pStages				= shaderStages.data();
3466 		createInfo.pVertexInputState	= &vertexInputState;
3467 		createInfo.pInputAssemblyState	= &inputAssemblyState;
3468 		createInfo.pTessellationState	= m_params.isTessellation() ? &tesselationState : nullptr;
3469 		createInfo.pViewportState		= &viewportState;
3470 		createInfo.pRasterizationState	= &rasterizationState;
3471 		createInfo.pMultisampleState	= &multisampleState;
3472 		createInfo.pDepthStencilState	= &depthStencilState;
3473 		createInfo.pColorBlendState		= &colorBlendState;
3474 		createInfo.pDynamicState		= nullptr;
3475 		createInfo.layout				= *m_pipelineLayout;
3476 		createInfo.renderPass			= *m_renderPass;
3477 		createInfo.subpass				= 0;
3478 		createInfo.basePipelineHandle	= DE_NULL;
3479 		createInfo.basePipelineIndex	= -1;
3480 		createInfo.flags				= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
3481 
3482 		m_pipeline = vk::createGraphicsPipeline(
3483 			*m_deviceInterface,
3484 			*m_device,
3485 			DE_NULL, // pipeline cache
3486 			&createInfo);
3487 	}
3488 }
3489 
createBufferForBinding(ResourceHolder & resources,VkDescriptorType descriptorType,VkBufferCreateInfo createInfo,bool isResultBuffer) const3490 void DescriptorBufferTestInstance::createBufferForBinding(
3491 	ResourceHolder&		resources,
3492 	VkDescriptorType	descriptorType,
3493 	VkBufferCreateInfo	createInfo,
3494 	bool				isResultBuffer) const
3495 {
3496 	auto& bufferResource	= resources.buffer;
3497 	auto& captureReplayData	= resources.captureReplay.bufferData;
3498 
3499 	createInfo.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
3500 
3501 	if (!isResultBuffer && isCaptureDescriptor(descriptorType))
3502 	{
3503 		createInfo.flags |= VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT;
3504 
3505 		DE_ASSERT(!bufferResource.buffer);
3506 		bufferResource.buffer = createBuffer(*m_deviceInterface, *m_device, &createInfo);
3507 
3508 		VkBufferCaptureDescriptorDataInfoEXT info = initVulkanStructure();
3509 		info.buffer = *bufferResource.buffer;
3510 
3511 		DE_ASSERT(captureReplayData.empty());
3512 		captureReplayData.resize(m_descriptorBufferProperties.bufferCaptureReplayDescriptorDataSize);
3513 
3514 		VK_CHECK(m_deviceInterface->getBufferOpaqueCaptureDescriptorDataEXT(*m_device, &info, captureReplayData.data()));
3515 	}
3516 	else if (!isResultBuffer && isReplayDescriptor(descriptorType))
3517 	{
3518 		// Free the previous buffer and its memory
3519 		reset(bufferResource.buffer);
3520 		reset(bufferResource.alloc);
3521 
3522 		DE_ASSERT(!captureReplayData.empty());
3523 
3524 		VkOpaqueCaptureDescriptorDataCreateInfoEXT info = initVulkanStructure();
3525 		info.opaqueCaptureDescriptorData = captureReplayData.data();
3526 
3527 		createInfo.flags |= VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT;
3528 		createInfo.pNext = &info;
3529 
3530 		bufferResource.buffer = createBuffer(*m_deviceInterface, *m_device, &createInfo);
3531 	}
3532 	else
3533 	{
3534 		DE_ASSERT(!bufferResource.buffer);
3535 		bufferResource.buffer = createBuffer(*m_deviceInterface, *m_device, &createInfo);
3536 	}
3537 
3538 	auto memReqs = getBufferMemoryRequirements(*m_deviceInterface, *m_device, *bufferResource.buffer);
3539 
3540 	VkMemoryOpaqueCaptureAddressAllocateInfo	opaqueCaptureAddressAllocateInfo	= initVulkanStructure();
3541 	VkMemoryAllocateFlagsInfo					allocFlagsInfo						= initVulkanStructure();
3542 	allocFlagsInfo.flags |= VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
3543 
3544 	if (!isResultBuffer && m_params.isCaptureReplayDescriptor(descriptorType))
3545 	{
3546 		allocFlagsInfo.flags |= VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT;
3547 		allocFlagsInfo.pNext = &opaqueCaptureAddressAllocateInfo;
3548 
3549 		if (isCaptureDescriptor(descriptorType))
3550 		{
3551 			opaqueCaptureAddressAllocateInfo.opaqueCaptureAddress = 0ull;
3552 		}
3553 		else if (isReplayDescriptor(descriptorType))
3554 		{
3555 			opaqueCaptureAddressAllocateInfo.opaqueCaptureAddress = bufferResource.opaqueCaptureAddress;
3556 		}
3557 	}
3558 
3559 	DE_ASSERT(!bufferResource.alloc);
3560 	bufferResource.alloc = allocate(memReqs, MemoryRequirement::HostVisible, &allocFlagsInfo);
3561 
3562 	if (isCaptureDescriptor(descriptorType))
3563 	{
3564 		VkDeviceMemoryOpaqueCaptureAddressInfo memoryOpaqueCaptureAddressInfo = initVulkanStructure();
3565 
3566 		memoryOpaqueCaptureAddressInfo.memory = bufferResource.alloc->getMemory();
3567 
3568 		bufferResource.opaqueCaptureAddress = m_deviceInterface->getDeviceMemoryOpaqueCaptureAddress(*m_device, &memoryOpaqueCaptureAddressInfo);
3569 	}
3570 
3571 	VK_CHECK(m_deviceInterface->bindBufferMemory(
3572 		*m_device,
3573 		*bufferResource.buffer,
3574 		bufferResource.alloc->getMemory(),
3575 		bufferResource.alloc->getOffset()));
3576 
3577 	bufferResource.loadDeviceAddress(*m_deviceInterface, *m_device);
3578 }
3579 
createImageForBinding(ResourceHolder & resources,VkDescriptorType descriptorType) const3580 void DescriptorBufferTestInstance::createImageForBinding(
3581 	ResourceHolder&		resources,
3582 	VkDescriptorType	descriptorType) const
3583 {
3584 	auto& imageResource	= resources.image;
3585 
3586 	// Image
3587 	auto& captureReplayData = resources.captureReplay.imageData;
3588 
3589 	if (isCaptureDescriptor(descriptorType))
3590 	{
3591 		imageResource.info.flags |= VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT;
3592 
3593 		DE_ASSERT(!imageResource.image);
3594 		imageResource.image = createImage(*m_deviceInterface, *m_device, &imageResource.info);
3595 
3596 		VkImageCaptureDescriptorDataInfoEXT info = initVulkanStructure();
3597 		info.image = *imageResource.image;
3598 
3599 		DE_ASSERT(captureReplayData.empty());
3600 		captureReplayData.resize(m_descriptorBufferProperties.imageCaptureReplayDescriptorDataSize);
3601 
3602 		VK_CHECK(m_deviceInterface->getImageOpaqueCaptureDescriptorDataEXT(*m_device, &info, captureReplayData.data()));
3603 	}
3604 	else if (isReplayDescriptor(descriptorType))
3605 	{
3606 		// Free the previous image and its memory
3607 		reset(imageResource.image);
3608 		reset(imageResource.alloc);
3609 
3610 		DE_ASSERT(!captureReplayData.empty());
3611 
3612 		VkOpaqueCaptureDescriptorDataCreateInfoEXT info = initVulkanStructure();
3613 		info.opaqueCaptureDescriptorData = captureReplayData.data();
3614 
3615 		imageResource.info.flags |= VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT;
3616 		imageResource.info.pNext = &info;
3617 
3618 		imageResource.image = createImage(*m_deviceInterface, *m_device, &imageResource.info);
3619 	}
3620 	else
3621 	{
3622 		DE_ASSERT(!imageResource.image);
3623 		imageResource.image = createImage(*m_deviceInterface, *m_device, &imageResource.info);
3624 	}
3625 
3626 	// Memory allocation
3627 	auto memReqs = getImageMemoryRequirements(*m_deviceInterface, *m_device, *imageResource.image);
3628 
3629 	VkMemoryOpaqueCaptureAddressAllocateInfo	opaqueCaptureAddressAllocateInfo	= initVulkanStructure();
3630 	VkMemoryAllocateFlagsInfo					allocFlagsInfo						= initVulkanStructure();
3631 
3632 	if (m_params.isCaptureReplayDescriptor(descriptorType))
3633 	{
3634 		allocFlagsInfo.flags |= VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT | VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
3635 		allocFlagsInfo.pNext = &opaqueCaptureAddressAllocateInfo;
3636 
3637 		if (isCaptureDescriptor(descriptorType))
3638 		{
3639 			opaqueCaptureAddressAllocateInfo.opaqueCaptureAddress = 0ull;
3640 		}
3641 		else if (isReplayDescriptor(descriptorType))
3642 		{
3643 			opaqueCaptureAddressAllocateInfo.opaqueCaptureAddress = imageResource.opaqueCaptureAddress;
3644 		}
3645 	}
3646 
3647 	DE_ASSERT(!imageResource.alloc);
3648 	imageResource.sizeBytes	= memReqs.size;
3649 	imageResource.alloc		= allocate(memReqs, MemoryRequirement::Local, &allocFlagsInfo);
3650 
3651 	if (isCaptureDescriptor(descriptorType))
3652 	{
3653 		VkDeviceMemoryOpaqueCaptureAddressInfo memoryOpaqueCaptureAddressInfo = initVulkanStructure();
3654 
3655 		memoryOpaqueCaptureAddressInfo.memory = imageResource.alloc->getMemory();
3656 
3657 		imageResource.opaqueCaptureAddress = m_deviceInterface->getDeviceMemoryOpaqueCaptureAddress(*m_device, &memoryOpaqueCaptureAddressInfo);
3658 	}
3659 
3660 	VK_CHECK(m_deviceInterface->bindImageMemory(
3661 		*m_device,
3662 		*imageResource.image,
3663 		imageResource.alloc->getMemory(),
3664 		imageResource.alloc->getOffset()));
3665 
3666 	// Image view
3667 	{
3668 		auto& captureReplayDataView = resources.captureReplay.imageViewData;
3669 
3670 		DE_ASSERT(imageResource.info.imageType == VK_IMAGE_TYPE_2D);
3671 
3672 		VkImageViewCreateInfo createInfo = initVulkanStructure();
3673 		createInfo.image			= *imageResource.image;
3674 		createInfo.viewType			= VK_IMAGE_VIEW_TYPE_2D;
3675 		createInfo.format			= imageResource.info.format;
3676 		createInfo.components		= ComponentMappingIdentity;
3677 		createInfo.subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
3678 
3679 		if (isCaptureDescriptor(descriptorType))
3680 		{
3681 			createInfo.flags |= VK_IMAGE_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT;
3682 
3683 			DE_ASSERT(!imageResource.imageView);
3684 			imageResource.imageView = createImageView(*m_deviceInterface, *m_device, &createInfo);
3685 
3686 			VkImageViewCaptureDescriptorDataInfoEXT info = initVulkanStructure();
3687 			info.imageView = *imageResource.imageView;
3688 
3689 			DE_ASSERT(captureReplayDataView.empty());
3690 			captureReplayDataView.resize(m_descriptorBufferProperties.imageViewCaptureReplayDescriptorDataSize);
3691 
3692 			VK_CHECK(m_deviceInterface->getImageViewOpaqueCaptureDescriptorDataEXT(*m_device, &info, captureReplayDataView.data()));
3693 		}
3694 		else if (isReplayDescriptor(descriptorType))
3695 		{
3696 			reset(imageResource.imageView);
3697 
3698 			DE_ASSERT(!captureReplayDataView.empty());
3699 
3700 			VkOpaqueCaptureDescriptorDataCreateInfoEXT info = initVulkanStructure();
3701 			info.opaqueCaptureDescriptorData = captureReplayDataView.data();
3702 
3703 			createInfo.flags |= VK_IMAGE_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT;
3704 			createInfo.pNext = &info;
3705 
3706 			imageResource.imageView = createImageView(*m_deviceInterface, *m_device, &createInfo);
3707 		}
3708 		else
3709 		{
3710 			// No assertion here, as we must create a new view to go with the image.
3711 			imageResource.imageView = createImageView(*m_deviceInterface, *m_device, &createInfo);
3712 		}
3713 	}
3714 }
3715 
3716 // This function prepares a descriptor binding for use:
3717 // - Create necessary buffer/image resources and initialize them
3718 // - Write descriptor data into the descriptor buffer
3719 // - Fix the memory layout of combined image samplers (if needed)
3720 //
initializeBinding(const DescriptorSetLayoutHolder & dsl,deUint32 setIndex,Binding & binding)3721 void DescriptorBufferTestInstance::initializeBinding(
3722 	const DescriptorSetLayoutHolder&	dsl,
3723 	deUint32							setIndex,
3724 	Binding&							binding)
3725 {
3726 	const auto arrayCount = (binding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) ?
3727 		1 : binding.descriptorCount;
3728 
3729 	const bool mustSplitCombinedImageSampler =
3730 		(arrayCount > 1) &&
3731 		(binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
3732 		(m_descriptorBufferProperties.combinedImageSamplerDescriptorSingleArray == VK_FALSE);
3733 
3734 	const bool isRobustBufferAccess = (m_params.variant == TestVariant::ROBUST_BUFFER_ACCESS);
3735 	const bool isNullDescriptor =
3736 		(m_params.variant == TestVariant::ROBUST_NULL_DESCRIPTOR) &&
3737 		(binding.descriptorType == m_params.descriptor) &&
3738 		 binding.isTestableDescriptor();
3739 
3740 	for (deUint32 arrayIndex = 0; arrayIndex < arrayCount; ++arrayIndex)
3741 	{
3742 		VkDescriptorGetInfoEXT		descGetInfo	= initVulkanStructure();
3743 		VkDescriptorAddressInfoEXT	addressInfo	= initVulkanStructure();
3744 		VkDescriptorImageInfo		imageInfo	{0, 0, VK_IMAGE_LAYOUT_UNDEFINED};	// must be explicitly initialized due to CTS handles inside
3745 
3746 		descGetInfo.type = VK_DESCRIPTOR_TYPE_MAX_ENUM;
3747 
3748 		if ((binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
3749 			(binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER))
3750 		{
3751 			auto& resources		 = getOrCreateResource(binding, arrayIndex);
3752 			auto& bufferResource = resources.buffer;
3753 
3754 			const VkBufferUsageFlags usage =
3755 				(binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT :
3756 				(binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : 0;
3757 			DE_ASSERT(usage);
3758 
3759 			bufferResource.size = sizeof(deUint32) * (binding.isResultBuffer ? ConstResultBufferDwords : ConstUniformBufferDwords);
3760 
3761 			createBufferForBinding(
3762 				resources,
3763 				binding.descriptorType,
3764 				makeBufferCreateInfo(bufferResource.size, usage),
3765 				binding.isResultBuffer);
3766 
3767 			deUint32* pBufferData = static_cast<deUint32*>(bufferResource.alloc->getHostPtr());
3768 
3769 			if (binding.isResultBuffer || isRobustBufferAccess)
3770 			{
3771 				// We zero the buffer if it's a result buffer or if it's used with robust access.
3772 				deMemset(pBufferData, 0, static_cast<std::size_t>(bufferResource.size));
3773 			}
3774 			else
3775 			{
3776 				const auto data = getExpectedData(m_params.hash, setIndex, binding.binding, arrayIndex);
3777 
3778 				for (deUint32 i = 0; i < ConstUniformBufferDwords; ++i)
3779 				{
3780 					pBufferData[i] = data + i;
3781 				}
3782 			}
3783 
3784 			addressInfo.address = bufferResource.deviceAddress;
3785 			addressInfo.range   = bufferResource.size;
3786 			addressInfo.format  = VK_FORMAT_UNDEFINED;
3787 
3788 			DE_UNREF(ConstRobustBufferAlignment);
3789 			DE_ASSERT(binding.isResultBuffer || !isRobustBufferAccess || ((addressInfo.range % ConstRobustBufferAlignment) == 0));
3790 
3791 			descGetInfo.type				= binding.descriptorType;
3792 			descGetInfo.data.pUniformBuffer = isNullDescriptor ? nullptr : &addressInfo;	// and pStorageBuffer
3793 		}
3794 		else if (binding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK)
3795 		{
3796 			// Inline uniforms don't use a backing buffer.
3797 			DE_ASSERT(binding.perBindingResourceIndex[arrayIndex] == INDEX_INVALID);
3798 		}
3799 		else if ((binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
3800 				 (binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER))
3801 		{
3802 			auto& resources		 = getOrCreateResource(binding, arrayIndex);
3803 			auto& bufferResource = resources.buffer;
3804 
3805 			const VkBufferUsageFlags usage =
3806 				(binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT :
3807 				(binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT : 0;
3808 			DE_ASSERT(usage);
3809 
3810 			bufferResource.size = ConstTexelBufferElements * sizeof(deUint32);
3811 
3812 			createBufferForBinding(
3813 				resources,
3814 				binding.descriptorType,
3815 				makeBufferCreateInfo(bufferResource.size, usage),
3816 				binding.isResultBuffer);
3817 
3818 			if (m_params.isPushDescriptorTest())
3819 			{
3820 				// Push descriptors use buffer views.
3821 				auto& bufferViewResource = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]).bufferView;
3822 
3823 				bufferViewResource = makeBufferView(
3824 					*m_deviceInterface,
3825 					*m_device,
3826 					*bufferResource.buffer,
3827 					VK_FORMAT_R32_UINT,
3828 					0,
3829 					bufferResource.size);
3830 			}
3831 
3832 			deUint32* pBufferData = static_cast<deUint32*>(bufferResource.alloc->getHostPtr());
3833 
3834 			if (isRobustBufferAccess)
3835 			{
3836 				// Zero the buffer used with robust access.
3837 				deMemset(pBufferData, 0, static_cast<std::size_t>(bufferResource.size));
3838 			}
3839 			else
3840 			{
3841 				const auto data = getExpectedData(m_params.hash, setIndex, binding.binding, arrayIndex);
3842 
3843 				for (deUint32 i = 0; i < ConstTexelBufferElements; ++i)
3844 				{
3845 					pBufferData[i] = data + i;
3846 				}
3847 			}
3848 
3849 			addressInfo.address = bufferResource.deviceAddress;
3850 			addressInfo.range	= bufferResource.size;
3851 			addressInfo.format	= VK_FORMAT_R32_UINT;
3852 
3853 			DE_UNREF(ConstRobustBufferAlignment);
3854 			DE_ASSERT(!isRobustBufferAccess || ((addressInfo.range % ConstRobustBufferAlignment) == 0));
3855 
3856 			descGetInfo.type					 = binding.descriptorType;
3857 			descGetInfo.data.pUniformTexelBuffer = isNullDescriptor ? nullptr : &addressInfo;	// and pStorageTexelBuffer
3858 		}
3859 		else if ((binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
3860 				 (binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
3861 				 (binding.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ||
3862 				 (binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER))
3863 		{
3864 			// Check if we had already added the resource while handling samplers.
3865 			auto& resources		= getOrCreateResource(binding, arrayIndex);
3866 			auto& imageResource = resources.image;
3867 			auto& stagingBuffer = resources.buffer;
3868 
3869 			{
3870 				VkImageLayout	  layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
3871 				VkImageUsageFlags usage  = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3872 
3873 				if (binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
3874 				{
3875 					usage |= VK_IMAGE_USAGE_STORAGE_BIT;
3876 					layout = VK_IMAGE_LAYOUT_GENERAL;
3877 				}
3878 				else if (binding.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
3879 				{
3880 					usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
3881 				}
3882 				else
3883 				{
3884 					usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
3885 				}
3886 
3887 				// We ensure the extent matches the render area, for the sake of input attachment case.
3888 				imageResource.info = initVulkanStructure();
3889 				imageResource.info.flags					= 0;
3890 				imageResource.info.imageType				= VK_IMAGE_TYPE_2D;
3891 				imageResource.info.format					= VK_FORMAT_R32_UINT;
3892 				imageResource.info.extent.width				= m_renderArea.extent.width;
3893 				imageResource.info.extent.height			= m_renderArea.extent.height;
3894 				imageResource.info.extent.depth				= 1;
3895 				imageResource.info.mipLevels				= 1;
3896 				imageResource.info.arrayLayers				= 1;
3897 				imageResource.info.samples					= VK_SAMPLE_COUNT_1_BIT;
3898 				imageResource.info.tiling					= VK_IMAGE_TILING_OPTIMAL;
3899 				imageResource.info.usage					= usage;
3900 				imageResource.info.sharingMode				= VK_SHARING_MODE_EXCLUSIVE;
3901 				imageResource.info.queueFamilyIndexCount	= 0;
3902 				imageResource.info.pQueueFamilyIndices		= nullptr;
3903 				imageResource.info.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
3904 
3905 				createImageForBinding(resources, binding.descriptorType);
3906 
3907 				imageResource.layout = layout;
3908 
3909 				imageInfo.imageLayout = layout;
3910 				imageInfo.imageView   = *imageResource.imageView;
3911 
3912 				descGetInfo.type = binding.descriptorType;
3913 
3914 				if (binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
3915 				{
3916 					if (isNullDescriptor)
3917 						imageInfo.imageView = DE_NULL;
3918 
3919 					descGetInfo.data.pCombinedImageSampler = &imageInfo;
3920 				}
3921 				else
3922 					descGetInfo.data.pStorageImage = isNullDescriptor ? nullptr : &imageInfo;
3923 			}
3924 			{
3925 				const auto numPixels = m_renderArea.extent.width * m_renderArea.extent.height;
3926 				stagingBuffer.size = sizeof(deUint32) * numPixels;
3927 				auto createInfo = makeBufferCreateInfo(stagingBuffer.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
3928 
3929 				stagingBuffer.buffer = createBuffer(*m_deviceInterface, *m_device, &createInfo);
3930 
3931 				auto memReqs = getBufferMemoryRequirements(*m_deviceInterface, *m_device, *stagingBuffer.buffer);
3932 
3933 				stagingBuffer.alloc = allocate(memReqs, MemoryRequirement::HostVisible);
3934 
3935 				VK_CHECK(m_deviceInterface->bindBufferMemory(
3936 					*m_device,
3937 					*stagingBuffer.buffer,
3938 					stagingBuffer.alloc->getMemory(),
3939 					stagingBuffer.alloc->getOffset()));
3940 
3941 				// Fill the whole image uniformly
3942 				deUint32* pBufferData = static_cast<deUint32*>(stagingBuffer.alloc->getHostPtr());
3943 				deUint32 expectedData;
3944 
3945 				if (binding.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
3946 				{
3947 					expectedData = getExpectedData(m_params.hash, setIndex, binding.binding, binding.inputAttachmentIndex + arrayIndex);
3948 				}
3949 				else
3950 				{
3951 					expectedData = getExpectedData(m_params.hash, setIndex, binding.binding, arrayIndex);
3952 				}
3953 
3954 				std::fill(pBufferData, pBufferData + numPixels, expectedData);
3955 			}
3956 
3957 			if (binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
3958 			{
3959 				DE_ASSERT(m_params.variant != TestVariant::EMBEDDED_IMMUTABLE_SAMPLERS);
3960 
3961 				DE_ASSERT(binding.perBindingResourceIndex[arrayIndex] != INDEX_INVALID);
3962 				auto& resourceSampler = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]).sampler;
3963 
3964 				imageInfo.sampler = *resourceSampler;
3965 			}
3966 		}
3967 		else if (binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
3968 		{
3969 			if (m_params.variant != TestVariant::EMBEDDED_IMMUTABLE_SAMPLERS)
3970 			{
3971 				DE_ASSERT(binding.perBindingResourceIndex[arrayIndex] != INDEX_INVALID);
3972 				auto& resourceSampler = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]).sampler;
3973 
3974 				descGetInfo.type = binding.descriptorType;
3975 				descGetInfo.data.pSampler = &*resourceSampler;
3976 			}
3977 		}
3978 		else if (binding.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
3979 		{
3980 			Allocator&									allocator		= *m_allocatorPtr;
3981 			const deUint32								expectedData	= getExpectedData(m_params.hash, setIndex, binding.binding, arrayIndex);
3982 			const float									zDepth			= float(expectedData);
3983 			const std::vector<tcu::Vec3>				vertices
3984 			{
3985 				tcu::Vec3(-1.0f, -1.0f, zDepth),
3986 				tcu::Vec3(-1.0f,  1.0f, zDepth),
3987 				tcu::Vec3( 1.0f, -1.0f, zDepth),
3988 
3989 				tcu::Vec3(-1.0f,  1.0f, zDepth),
3990 				tcu::Vec3( 1.0f,  1.0f, zDepth),
3991 				tcu::Vec3( 1.0f, -1.0f, zDepth),
3992 			};
3993 			auto&										resources			= getOrCreateResource(binding, arrayIndex);
3994 			const bool									replayableBinding	= binding.isTestableDescriptor();
3995 			VkAccelerationStructureCreateFlagsKHR		createFlags			= (m_params.isCaptureReplayDescriptor(binding.descriptorType) && replayableBinding)
3996 																			? static_cast<VkAccelerationStructureCreateFlagsKHR>(VK_ACCELERATION_STRUCTURE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT)
3997 																			: static_cast<VkAccelerationStructureCreateFlagsKHR>(0u);
3998 			vk::MemoryRequirement						memoryReqs			= (m_params.isCaptureReplayDescriptor(binding.descriptorType) && replayableBinding)
3999 																			? MemoryRequirement::DeviceAddressCaptureReplay
4000 																			: MemoryRequirement::Any;
4001 			VkOpaqueCaptureDescriptorDataCreateInfoEXT	infos[]				= { initVulkanStructure(), initVulkanStructure() };
4002 			VkOpaqueCaptureDescriptorDataCreateInfoEXT*	infoPtrs[]			= { DE_NULL, DE_NULL };
4003 
4004 			if (isReplayDescriptor(binding.descriptorType) && replayableBinding)
4005 			{
4006 				resources.rtBlas.clear();
4007 				resources.rtTlas.clear();
4008 
4009 				std::vector<deUint8>* captureReplayDatas[] = { &resources.captureReplay.accelerationStructureDataBlas, &resources.captureReplay.accelerationStructureDataTlas };
4010 
4011 				for (int ndx = 0; ndx < 2; ++ndx)
4012 				{
4013 					std::vector<deUint8>&						captureReplayData	= *captureReplayDatas[ndx];
4014 					VkOpaqueCaptureDescriptorDataCreateInfoEXT&	info				= infos[ndx];
4015 
4016 					info.opaqueCaptureDescriptorData = captureReplayData.data();
4017 					infoPtrs[ndx] = &infos[ndx];
4018 				}
4019 			}
4020 
4021 			{
4022 				DE_ASSERT(resources.rtBlas.get() == DE_NULL);
4023 
4024 				resources.rtBlas = de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
4025 				if (binding.isRayTracingAS)
4026 					resources.rtBlas->setDefaultGeometryData(m_params.stage);
4027 				else
4028 					resources.rtBlas->setGeometryData(vertices, true);
4029 				resources.rtBlas->setCreateFlags(createFlags);
4030 				resources.rtBlas->create(*m_deviceInterface, *m_device, allocator, 0, 0, infoPtrs[0], memoryReqs);
4031 			}
4032 
4033 			{
4034 				DE_ASSERT(resources.rtTlas.get() == DE_NULL);
4035 
4036 				resources.rtTlas = makeTopLevelAccelerationStructure();
4037 				resources.rtTlas->addInstance(resources.rtBlas);
4038 				resources.rtTlas->setCreateFlags(createFlags);
4039 				resources.rtTlas->create(*m_deviceInterface, *m_device, allocator, 0, 0, infoPtrs[1], memoryReqs);
4040 			}
4041 
4042 			if (isCaptureDescriptor(binding.descriptorType) && replayableBinding)
4043 			{
4044 				const VkAccelerationStructureKHR*	accelerationStructures[]	= { resources.rtBlas->getPtr() , resources.rtTlas->getPtr() };
4045 				std::vector<deUint8>*				captureReplayDatas[]		= { &resources.captureReplay.accelerationStructureDataBlas, &resources.captureReplay.accelerationStructureDataTlas };
4046 
4047 				for (int ndx = 0; ndx < 2; ++ndx)
4048 				{
4049 					VkAccelerationStructureCaptureDescriptorDataInfoEXT	info					= initVulkanStructure();
4050 					const VkAccelerationStructureKHR*					accelerationStructure	= accelerationStructures[ndx];
4051 					std::vector<deUint8>&								captureReplayData		= *captureReplayDatas[ndx];
4052 
4053 					DE_ASSERT(accelerationStructure != DE_NULL && *accelerationStructure != DE_NULL);
4054 					DE_ASSERT(captureReplayData.empty());
4055 
4056 					info.accelerationStructure = *accelerationStructure;
4057 
4058 					captureReplayData.resize(m_descriptorBufferProperties.accelerationStructureCaptureReplayDescriptorDataSize);
4059 
4060 					VK_CHECK(m_deviceInterface->getAccelerationStructureOpaqueCaptureDescriptorDataEXT(*m_device, &info, captureReplayData.data()));
4061 				}
4062 			}
4063 
4064 			descGetInfo.type = binding.descriptorType;
4065 			descGetInfo.data.accelerationStructure	= isNullDescriptor ? DE_NULL : getAccelerationStructureDeviceAddress(*m_deviceInterface, *m_device, *resources.rtTlas->getPtr());
4066 		}
4067 		else
4068 		{
4069 			TCU_THROW(InternalError, "Not implemented");
4070 		}
4071 
4072 		if (dsl.usePushDescriptors || dsl.sizeOfLayout == 0)
4073 		{
4074 			// Push descriptors don't rely on descriptor buffers, move to the next binding.
4075 			continue;
4076 		}
4077 
4078 		// Write the descriptor at the right offset in the descriptor buffer memory.
4079 		// - With inline uniform blocks, we write the uniform data into the descriptor buffer directly.
4080 		// - With regular descriptors, the written memory is opaque to us (same goes for null descriptors).
4081 		{
4082 			void*		bindingHostPtr	= nullptr;
4083 			Allocation* pAlloc			= nullptr;
4084 			const auto	arrayOffset		= arrayIndex * getDescriptorSize(binding);
4085 
4086 			if (dsl.stagingBufferOffset == OFFSET_UNUSED)
4087 			{
4088 				const auto& descriptorBuffer = *m_descriptorBuffers[dsl.bufferIndex];
4089 				const auto bufferHostPtr = offsetPtr(descriptorBuffer.alloc->getHostPtr(), dsl.bufferOffset);
4090 
4091 				bindingHostPtr = offsetPtr(bufferHostPtr, binding.offset);
4092 				pAlloc = descriptorBuffer.alloc.get();
4093 			}
4094 			else
4095 			{
4096 				bindingHostPtr = offsetPtr(
4097 					m_descriptorStagingBuffer.alloc->getHostPtr(),
4098 					dsl.stagingBufferOffset + binding.offset);
4099 
4100 				pAlloc = m_descriptorStagingBuffer.alloc.get();
4101 			}
4102 
4103 			if (binding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK)
4104 			{
4105 				DE_ASSERT(arrayIndex == 0);
4106 
4107 				// Inline uniform data is written in descriptor buffer directly.
4108 				const auto numDwords = binding.descriptorCount / sizeof(deUint32);
4109 				const auto data		 = getExpectedData(m_params.hash, setIndex, binding.binding, arrayIndex);
4110 
4111 				deUint32* pInlineData = static_cast<deUint32*>(bindingHostPtr);
4112 
4113 				for (deUint32 i = 0; i < numDwords; ++i)
4114 				{
4115 					pInlineData[i] = data + i;
4116 				}
4117 			}
4118 			else if (isReplayDescriptor(binding.descriptorType))
4119 			{
4120 				// We're expecting that a descriptor based on replayed resources will have exactly the same binary data.
4121 				// Copy it and compare after obtaining the new descriptor.
4122 				//
4123 				auto		descriptorPtr  = offsetPtr(bindingHostPtr, arrayOffset);
4124 				const auto  descriptorSize = static_cast<size_t>(getDescriptorSize(binding));
4125 
4126 				std::vector<deUint8> reference(descriptorSize);
4127 				deMemcpy(reference.data(), descriptorPtr, descriptorSize);
4128 
4129 				deMemset(descriptorPtr, 0xcc, descriptorSize);
4130 				m_deviceInterface->getDescriptorEXT(*m_device, &descGetInfo, descriptorSize, descriptorPtr);
4131 
4132 				if (deMemCmp(reference.data(), descriptorPtr, descriptorSize) != 0)
4133 				{
4134 					TCU_THROW(TestError, "Replayed descriptor differs from the captured descriptor");
4135 				}
4136 			}
4137 			else
4138 			{
4139 				auto		descriptorPtr  = offsetPtr(bindingHostPtr, arrayOffset);
4140 				const auto  descriptorSize = static_cast<size_t>(getDescriptorSize(binding));
4141 				m_deviceInterface->getDescriptorEXT(*m_device, &descGetInfo, descriptorSize, descriptorPtr);
4142 			}
4143 
4144 			// After writing the last array element, rearrange the split combined image sampler data.
4145 			if (mustSplitCombinedImageSampler && ((arrayIndex + 1) == arrayCount))
4146 			{
4147 				// We determined the size of the descriptor set layout on the VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type,
4148 				// so it's expected the following holds true.
4149 				DE_ASSERT((m_descriptorBufferProperties.sampledImageDescriptorSize + m_descriptorBufferProperties.samplerDescriptorSize) ==
4150 					m_descriptorBufferProperties.combinedImageSamplerDescriptorSize);
4151 
4152 				std::vector<deUint8> scratchSpace(
4153 					arrayCount * m_descriptorBufferProperties.combinedImageSamplerDescriptorSize);
4154 
4155 				const auto descriptorArraySize = static_cast<std::size_t>(arrayCount * m_descriptorBufferProperties.combinedImageSamplerDescriptorSize);
4156 
4157 				deMemcpy(scratchSpace.data(), bindingHostPtr, descriptorArraySize);
4158 				deMemset(bindingHostPtr, 0, descriptorArraySize);
4159 
4160 				const void*	combinedReadPtr = scratchSpace.data();
4161 				void*		imageWritePtr   = bindingHostPtr;
4162 				void*		samplerWritePtr = offsetPtr(bindingHostPtr, arrayCount * m_descriptorBufferProperties.sampledImageDescriptorSize);
4163 
4164 				for (deUint32 i = 0; i < arrayCount; ++i)
4165 				{
4166 					deMemcpy(imageWritePtr,		offsetPtr(combinedReadPtr, 0),														 m_descriptorBufferProperties.sampledImageDescriptorSize);
4167 					deMemcpy(samplerWritePtr,	offsetPtr(combinedReadPtr, m_descriptorBufferProperties.sampledImageDescriptorSize), m_descriptorBufferProperties.samplerDescriptorSize);
4168 
4169 					combinedReadPtr	= offsetPtr(combinedReadPtr, m_descriptorBufferProperties.combinedImageSamplerDescriptorSize);
4170 					imageWritePtr	= offsetPtr(imageWritePtr,   m_descriptorBufferProperties.sampledImageDescriptorSize);
4171 					samplerWritePtr	= offsetPtr(samplerWritePtr, m_descriptorBufferProperties.samplerDescriptorSize);
4172 				}
4173 			}
4174 
4175 			flushAlloc(*m_deviceInterface, *m_device, *pAlloc);
4176 		}
4177 	}
4178 }
4179 
4180 // Update a descriptor set with a push or a push template.
4181 //
pushDescriptorSet(VkCommandBuffer cmdBuf,VkPipelineBindPoint bindPoint,const DescriptorSetLayoutHolder & dsl,deUint32 setIndex) const4182 void DescriptorBufferTestInstance::pushDescriptorSet(
4183 		VkCommandBuffer						cmdBuf,
4184 		VkPipelineBindPoint					bindPoint,
4185 		const DescriptorSetLayoutHolder&	dsl,
4186 		deUint32							setIndex) const
4187 {
4188 	std::vector<PushDescriptorData>								descriptorData(dsl.bindings.size());	// Allocate empty elements upfront
4189 	std::vector<VkWriteDescriptorSet>							descriptorWrites;
4190 	std::vector<VkWriteDescriptorSetAccelerationStructureKHR>	descriptorWritesAccelerationStructures;
4191 
4192 	descriptorWrites.reserve(dsl.bindings.size());
4193 	descriptorWritesAccelerationStructures.reserve(dsl.bindings.size());
4194 
4195 	// Fill in the descriptor data structure. It can be used by the regular and templated update path.
4196 
4197 	for (deUint32 bindingIndex = 0; bindingIndex < u32(dsl.bindings.size()); ++bindingIndex)
4198 	{
4199 		const auto& binding = dsl.bindings[bindingIndex];
4200 
4201 		VkWriteDescriptorSet write = initVulkanStructure();
4202 		write.dstSet			= DE_NULL;	// ignored with push descriptors
4203 		write.dstBinding		= bindingIndex;
4204 		write.dstArrayElement	= 0;
4205 		write.descriptorCount	= binding.descriptorCount;
4206 		write.descriptorType	= binding.descriptorType;
4207 
4208 		for (deUint32 arrayIndex = 0; arrayIndex < write.descriptorCount; ++arrayIndex)
4209 		{
4210 			DE_ASSERT(binding.perBindingResourceIndex[arrayIndex] != INDEX_INVALID);
4211 
4212 			if ((binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
4213 				(binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER))
4214 			{
4215 				const auto& bufferResource = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]).buffer;
4216 
4217 				auto pInfo = &descriptorData[bindingIndex].bufferInfos[arrayIndex];
4218 				pInfo->buffer = *bufferResource.buffer;
4219 				pInfo->offset = 0;
4220 				pInfo->range  = bufferResource.size;
4221 
4222 				if (arrayIndex == 0)
4223 				{
4224 					write.pBufferInfo = pInfo;
4225 				}
4226 			}
4227 			else if ((binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
4228 					 (binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER))
4229 			{
4230 				const auto& bufferViewResource = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]).bufferView;
4231 
4232 				auto pBufferView = &descriptorData[bindingIndex].texelBufferViews[arrayIndex];
4233 				*pBufferView = *bufferViewResource;
4234 
4235 				if (arrayIndex == 0)
4236 				{
4237 					write.pTexelBufferView = pBufferView;
4238 				}
4239 			}
4240 			else if ((binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
4241 					 (binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
4242 					 (binding.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ||
4243 					 (binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
4244 					 (binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER))
4245 			{
4246 				const auto& imageResource   = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]).image;
4247 				const auto& samplerResource = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]).sampler;
4248 
4249 				// Dereferencing unused resources will return null handles, so we can treat all these descriptors uniformly.
4250 
4251 				auto pInfo = &descriptorData[bindingIndex].imageInfos[arrayIndex];
4252 				pInfo->imageView   = *imageResource.imageView;
4253 				pInfo->imageLayout = imageResource.layout;
4254 				pInfo->sampler	   = *samplerResource;
4255 
4256 				if (arrayIndex == 0)
4257 				{
4258 					write.pImageInfo = pInfo;
4259 				}
4260 			}
4261 			else if (binding.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
4262 			{
4263 				const ResourceHolder&				resources					= **m_resources[binding.perBindingResourceIndex[arrayIndex]];
4264 				const VkAccelerationStructureKHR*	accelerationStructurePtr	= resources.rtTlas.get()->getPtr();
4265 
4266 				DE_ASSERT(accelerationStructurePtr != DE_NULL && *accelerationStructurePtr != DE_NULL);
4267 
4268 				descriptorData[bindingIndex].accelerationStructures[arrayIndex] = *accelerationStructurePtr;
4269 
4270 				if (arrayIndex == 0)
4271 				{
4272 					VkWriteDescriptorSetAccelerationStructureKHR	descriptorWritesAccelerationStructure = initVulkanStructure();
4273 
4274 					descriptorWritesAccelerationStructure.accelerationStructureCount = write.descriptorCount;
4275 					descriptorWritesAccelerationStructure.pAccelerationStructures = descriptorData[bindingIndex].accelerationStructures;
4276 
4277 					descriptorWritesAccelerationStructures.emplace_back(descriptorWritesAccelerationStructure);
4278 
4279 					write.pNext = &descriptorWritesAccelerationStructures[descriptorWritesAccelerationStructures.size() - 1];
4280 				}
4281 			}
4282 			else
4283 			{
4284 				TCU_THROW(InternalError, "Not implemented");
4285 			}
4286 		}
4287 
4288 		if (m_params.variant == TestVariant::PUSH_DESCRIPTOR)
4289 		{
4290 			descriptorWrites.emplace_back(write);
4291 		}
4292 	}
4293 
4294 	if (m_params.variant == TestVariant::PUSH_DESCRIPTOR)
4295 	{
4296 		m_deviceInterface->cmdPushDescriptorSetKHR(
4297 			cmdBuf,
4298 			bindPoint,
4299 			*m_pipelineLayout,
4300 			setIndex,
4301 			u32(descriptorWrites.size()),
4302 			descriptorWrites.data());
4303 	}
4304 	else if (m_params.variant == TestVariant::PUSH_TEMPLATE)
4305 	{
4306 		std::vector<VkDescriptorUpdateTemplateEntry> updateEntries(descriptorData.size());	// preallocate
4307 
4308 		const auto dataBasePtr = reinterpret_cast<deUint8*>(descriptorData.data());
4309 
4310 		for (deUint32 bindingIndex = 0; bindingIndex < u32(dsl.bindings.size()); ++bindingIndex)
4311 		{
4312 			const auto& binding = dsl.bindings[bindingIndex];
4313 			const auto& data    = descriptorData[bindingIndex];
4314 
4315 			auto& entry = updateEntries[bindingIndex];
4316 			entry.dstBinding		= binding.binding;
4317 			entry.dstArrayElement	= 0;
4318 			entry.descriptorCount	= binding.descriptorCount;
4319 			entry.descriptorType	= binding.descriptorType;
4320 
4321 			switch(binding.descriptorType)
4322 			{
4323 			case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
4324 			case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
4325 				entry.offset = basePtrOffsetOf(dataBasePtr, data.bufferInfos);
4326 				entry.stride = sizeof(data.bufferInfos[0]);
4327 				break;
4328 
4329 			case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
4330 			case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
4331 				entry.offset = basePtrOffsetOf(dataBasePtr, data.texelBufferViews);
4332 				entry.stride = sizeof(data.texelBufferViews[0]);
4333 				break;
4334 
4335 			case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
4336 			case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
4337 			case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
4338 			case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
4339 			case VK_DESCRIPTOR_TYPE_SAMPLER:
4340 				entry.offset = basePtrOffsetOf(dataBasePtr, data.imageInfos);
4341 				entry.stride = sizeof(data.imageInfos[0]);
4342 				break;
4343 
4344 			case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
4345 				entry.offset = basePtrOffsetOf(dataBasePtr, data.accelerationStructures);
4346 				entry.stride = sizeof(data.accelerationStructures[0]);
4347 				break;
4348 
4349 			default:
4350 				DE_ASSERT(0);
4351 				break;
4352 			}
4353 		}
4354 
4355 		VkDescriptorUpdateTemplateCreateInfo createInfo = initVulkanStructure();
4356 		createInfo.templateType					= VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR;
4357 		createInfo.descriptorSetLayout			= *dsl.layout;
4358 		createInfo.pipelineBindPoint			= bindPoint;
4359 		createInfo.pipelineLayout				= *m_pipelineLayout;
4360 		createInfo.set							= setIndex;
4361 		createInfo.descriptorUpdateEntryCount	= u32(updateEntries.size());
4362 		createInfo.pDescriptorUpdateEntries		= updateEntries.data();
4363 
4364 		auto descriptorUpdateTemplate = createDescriptorUpdateTemplate(
4365 			*m_deviceInterface,
4366 			*m_device,
4367 			&createInfo);
4368 
4369 		m_deviceInterface->cmdPushDescriptorSetWithTemplateKHR(
4370 			cmdBuf,
4371 			*descriptorUpdateTemplate,
4372 			*m_pipelineLayout,
4373 			setIndex,
4374 			dataBasePtr);
4375 	}
4376 }
4377 
4378 // Perform the test accoring to the parameters. At high level, all tests perform these steps:
4379 //
4380 // - Create a new device and queues, query extension properties.
4381 // - Fill descriptor set layouts and bindings, based on SimpleBinding's.
4382 // - Create samplers, if needed. Set immutable samplers in bindings.
4383 // - Create descriptor set layouts.
4384 // - Create descriptor buffers.
4385 // - Iterate over all bindings to:
4386 //   - Create their resources (images, buffers) and initialize them
4387 //   - Write bindings to descriptor buffer memory
4388 //   - Fix combined image samplers for arrayed bindings (if applicable)
4389 // - Create the pipeline layout, shaders, and the pipeline
4390 // - Create the command buffer and record the commands (barriers omitted for brevity):
4391 //   - Bind the pipeline and the descriptor buffers
4392 //   - Upload descriptor buffer data (with staged uploads)
4393 //   - Upload image data (if images are used)
4394 //   - Push descriptors (if used)
4395 //   - Dispatch or draw
4396 //   - Submit the commands
4397 //   - Map the result buffer to a host pointer
4398 //   - Verify the result and log diagnostic on a failure
4399 //
4400 // Verification logic is very simple.
4401 //
4402 // Each successful binding read will increment the result counter. If the shader got an unexpected value, the counter
4403 // will be less than expected. Additionally, the first failed set/binding/array index will be recorded.
4404 //
4405 // With capture/replay tests, iterate() will be called twice, splitting the test into capture and replay passes.
4406 // The capture pass saves the opaque data, while the replay pass uses it and compares the results.
4407 //
iterate()4408 tcu::TestStatus	DescriptorBufferTestInstance::iterate()
4409 {
4410 	DE_ASSERT(m_params.bufferBindingCount <= m_descriptorBufferProperties.maxDescriptorBufferBindings);
4411 
4412 	const auto& vk = *m_deviceInterface;
4413 
4414 	if (m_testIteration == 0)
4415 	{
4416 		deUint32 currentSet = INDEX_INVALID;
4417 
4418 		for (const auto& sb : m_simpleBindings)
4419 		{
4420 			if ((currentSet == INDEX_INVALID) || (currentSet < sb.set))
4421 			{
4422 				currentSet = sb.set;
4423 
4424 				addDescriptorSetLayout();
4425 			}
4426 
4427 			auto&				dsl			= **m_descriptorSetLayouts.back();
4428 			VkShaderStageFlags	stageFlags	= sb.isRayTracingAS
4429 											? static_cast<VkShaderStageFlags>(VK_SHADER_STAGE_RAYGEN_BIT_KHR)
4430 											: static_cast<VkShaderStageFlags>(0u);
4431 
4432 			Binding binding {};
4433 			binding.binding				 = sb.binding;
4434 			binding.descriptorType		 = sb.type;
4435 			binding.stageFlags			 = m_params.stage | stageFlags;
4436 			binding.inputAttachmentIndex = sb.inputAttachmentIndex;
4437 			binding.isResultBuffer		 = sb.isResultBuffer;
4438 			binding.isRayTracingAS		 = sb.isRayTracingAS;
4439 
4440 			if (sb.type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK)
4441 			{
4442 				binding.descriptorCount = sizeof(deUint32) * ConstInlineBlockDwords;
4443 			}
4444 			else
4445 			{
4446 				binding.descriptorCount = sb.count;
4447 			}
4448 
4449 			if ((sb.type == VK_DESCRIPTOR_TYPE_SAMPLER) ||
4450 				(sb.type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER))
4451 			{
4452 				if (sb.isEmbeddedImmutableSampler)
4453 				{
4454 					dsl.hasEmbeddedImmutableSamplers = true;
4455 				}
4456 			}
4457 
4458 			if (m_params.isPushDescriptorTest() &&
4459 				(m_params.pushDescriptorSetIndex == (m_descriptorSetLayouts.size() - 1)))
4460 			{
4461 				dsl.usePushDescriptors = true;
4462 			}
4463 
4464 			dsl.bindings.emplace_back(binding);
4465 		}
4466 	}
4467 
4468 	// We create samplers before creating the descriptor set layouts, in case we need to use
4469 	// immutable (or embedded) samplers.
4470 
4471 	for (deUint32 setIndex = 0; setIndex < u32(m_descriptorSetLayouts.size()); ++setIndex)
4472 	{
4473 		auto& dsl = **m_descriptorSetLayouts[setIndex];
4474 
4475 		for (deUint32 bindingIndex = 0; bindingIndex < u32(dsl.bindings.size()); ++bindingIndex)
4476 		{
4477 			auto& binding = dsl.bindings[bindingIndex];
4478 
4479 			if ((binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
4480 				(binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER))
4481 			{
4482 				for (deUint32 arrayIndex = 0; arrayIndex < binding.descriptorCount; ++arrayIndex)
4483 				{
4484 					if (binding.perBindingResourceIndex[arrayIndex] == INDEX_INVALID)
4485 					{
4486 						binding.perBindingResourceIndex[arrayIndex] = addResource();
4487 					}
4488 
4489 					auto& resources			= **m_resources[binding.perBindingResourceIndex[arrayIndex]];
4490 					auto& captureReplayData = resources.captureReplay.samplerData;
4491 
4492 					// Use CLAMP_TO_BORDER to verify that sampling outside the image will make use of the sampler's
4493 					// properties. The border color used must match the one in glslOutputVerification().
4494 
4495 					VkSamplerCreateInfo createInfo = initVulkanStructure();
4496 					createInfo.magFilter				= VK_FILTER_NEAREST;
4497 					createInfo.minFilter				= VK_FILTER_NEAREST;
4498 					createInfo.mipmapMode				= VK_SAMPLER_MIPMAP_MODE_NEAREST;
4499 					createInfo.addressModeU				= VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
4500 					createInfo.addressModeV				= VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
4501 					createInfo.addressModeW				= VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
4502 					createInfo.mipLodBias				= 0.0f;
4503 					createInfo.anisotropyEnable			= VK_FALSE;
4504 					createInfo.maxAnisotropy			= 1.0f;
4505 					createInfo.compareEnable			= VK_FALSE;
4506 					createInfo.compareOp				= VK_COMPARE_OP_NEVER;
4507 					createInfo.minLod					= 0.0;
4508 					createInfo.maxLod					= 0.0;
4509 					createInfo.borderColor				= VK_BORDER_COLOR_INT_OPAQUE_BLACK;
4510 					createInfo.unnormalizedCoordinates	= VK_FALSE;
4511 
4512 					VkSamplerCustomBorderColorCreateInfoEXT customBorderColorInfo = initVulkanStructure();
4513 
4514 					const void** nextPtr = &createInfo.pNext;
4515 
4516 					if (m_params.subcase == SubCase::CAPTURE_REPLAY_CUSTOM_BORDER_COLOR)
4517 					{
4518 						createInfo.borderColor = VK_BORDER_COLOR_INT_CUSTOM_EXT;
4519 
4520 						customBorderColorInfo.format			= VK_FORMAT_R32_UINT;
4521 						customBorderColorInfo.customBorderColor = makeClearValueColorU32(2, 0, 0, 1).color;
4522 
4523 						addToChainVulkanStructure(&nextPtr, customBorderColorInfo);
4524 					}
4525 
4526 					if (isCaptureDescriptor(VK_DESCRIPTOR_TYPE_SAMPLER) ||
4527 						isCaptureDescriptor(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER))
4528 					{
4529 						createInfo.flags |= VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT;
4530 
4531 						resources.sampler = createSampler(vk, *m_device, &createInfo);
4532 
4533 						VkSamplerCaptureDescriptorDataInfoEXT info = initVulkanStructure();
4534 						info.sampler = *resources.sampler;
4535 
4536 						DE_ASSERT(captureReplayData.empty());
4537 						captureReplayData.resize(m_descriptorBufferProperties.samplerCaptureReplayDescriptorDataSize);
4538 
4539 						VK_CHECK(m_deviceInterface->getSamplerOpaqueCaptureDescriptorDataEXT(*m_device, &info, captureReplayData.data()));
4540 					}
4541 					else if (isReplayDescriptor(VK_DESCRIPTOR_TYPE_SAMPLER) ||
4542 							 isReplayDescriptor(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER))
4543 					{
4544 						reset(resources.sampler);
4545 
4546 						DE_ASSERT(!captureReplayData.empty());
4547 
4548 						VkOpaqueCaptureDescriptorDataCreateInfoEXT info = initVulkanStructure();
4549 						info.opaqueCaptureDescriptorData = captureReplayData.data();
4550 
4551 						createInfo.flags |= VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT;
4552 
4553 						addToChainVulkanStructure(&nextPtr, info);
4554 
4555 						resources.sampler = createSampler(vk, *m_device, &createInfo);
4556 					}
4557 					else
4558 					{
4559 						resources.sampler = createSampler(vk, *m_device, &createInfo);
4560 					}
4561 				}
4562 			}
4563 		}
4564 	}
4565 
4566 	if ((m_params.variant == TestVariant::EMBEDDED_IMMUTABLE_SAMPLERS) ||
4567 		(m_params.subcase == SubCase::IMMUTABLE_SAMPLERS))
4568 	{
4569 		// Patch immutable sampler pointers, now that all memory has been allocated and pointers won't move.
4570 
4571 		for (deUint32 setIndex = 0; setIndex < u32(m_descriptorSetLayouts.size()); ++setIndex)
4572 		{
4573 			auto& dsl = **m_descriptorSetLayouts[setIndex];
4574 
4575 			for (deUint32 bindingIndex = 0; bindingIndex < u32(dsl.bindings.size()); ++bindingIndex)
4576 			{
4577 				auto& binding = dsl.bindings[bindingIndex];
4578 
4579 				for (deUint32 resourceIndex = 0; resourceIndex < DE_LENGTH_OF_ARRAY(binding.perBindingResourceIndex); ++resourceIndex)
4580 				{
4581 					if (binding.perBindingResourceIndex[resourceIndex] != INDEX_INVALID)
4582 					{
4583 						const auto& resources = **m_resources[binding.perBindingResourceIndex[resourceIndex]];
4584 
4585 						if (resources.sampler)
4586 						{
4587 							DE_ASSERT(resourceIndex < DE_LENGTH_OF_ARRAY(binding.immutableSamplers));
4588 
4589 							binding.immutableSamplers[resourceIndex] = *resources.sampler;
4590 						}
4591 					}
4592 				}
4593 			}
4594 		}
4595 	}
4596 
4597 	if (m_testIteration == 0)
4598 	{
4599 		createDescriptorSetLayouts();
4600 		createDescriptorBuffers();
4601 	}
4602 
4603 	for (deUint32 setIndex = 0; setIndex < u32(m_descriptorSetLayouts.size()); ++setIndex)
4604 	{
4605 		auto& dsl = **m_descriptorSetLayouts[setIndex];
4606 
4607 		if (dsl.hasEmbeddedImmutableSamplers)
4608 		{
4609 			// Embedded samplers are not written to the descriptor buffer directly.
4610 			continue;
4611 		}
4612 
4613 		for (deUint32 bindingIndex = 0; bindingIndex < u32(dsl.bindings.size()); ++bindingIndex)
4614 		{
4615 			auto& binding = dsl.bindings[bindingIndex];
4616 
4617 			// The descriptor bindings are initialized in two situations:
4618 			// 1. in the first test iteration (which is also the capture pass of capture/replay test)
4619 			// 2. in the replay pass, for the binding with the matching descriptor type
4620 			//
4621 			if ((m_testIteration == 0) ||
4622 				(binding.isTestableDescriptor() &&
4623 				 m_params.isCaptureReplayDescriptor(binding.descriptorType)))
4624 			{
4625 				initializeBinding(dsl, setIndex, binding);
4626 			}
4627 		}
4628 	}
4629 
4630 	{
4631 		VkPipelineLayoutCreateInfo createInfo = initVulkanStructure();
4632 		const auto dslCopy = getDescriptorSetLayouts(m_descriptorSetLayouts);
4633 		createInfo.setLayoutCount = u32(dslCopy.size());
4634 		createInfo.pSetLayouts = dslCopy.data();
4635 
4636 		m_pipelineLayout = createPipelineLayout(vk, *m_device, &createInfo);
4637 	}
4638 
4639 	if (m_params.isCompute())
4640 	{
4641 		const auto					shaderModule		= createShaderModule(vk, *m_device, getShaderBinary(VK_SHADER_STAGE_COMPUTE_BIT), 0u);
4642 		const VkSpecializationInfo* pSpecializationInfo = nullptr;
4643 
4644 		m_pipeline = makeComputePipeline(
4645 			vk,
4646 			*m_device,
4647 			*m_pipelineLayout,
4648 			VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT,
4649 			*shaderModule,
4650 			(VkPipelineShaderStageCreateFlags)0,
4651 			pSpecializationInfo);
4652 	}
4653 	else if (m_params.isRayTracing())
4654 	{
4655 		createRayTracingPipeline();
4656 	}
4657 	else
4658 	{
4659 		createGraphicsPipeline();
4660 	}
4661 
4662 	{
4663 		auto		cmdPool			= makeCommandPool(vk, *m_device, m_queueFamilyIndex);
4664 		auto		cmdBuf			= allocateCommandBuffer(vk, *m_device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4665 		const auto	bindPoint		= m_params.isCompute() ? VK_PIPELINE_BIND_POINT_COMPUTE
4666 									: m_params.isRayTracing() ? VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR
4667 									: m_params.isGraphics() ? VK_PIPELINE_BIND_POINT_GRAPHICS
4668 									: VK_PIPELINE_BIND_POINT_MAX_ENUM;
4669 		const auto	dstStageMask	= m_params.isCompute() ? VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT
4670 									: m_params.isRayTracing() ? VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR
4671 									: m_params.isGraphics() ? VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT
4672 									: VK_PIPELINE_STAGE_2_NONE;
4673 		const auto	dstStageMaskUp	= m_params.isCompute() ? VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT
4674 									: m_params.isRayTracing() ? VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR
4675 									: m_params.isGraphics() ? VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
4676 									: VK_PIPELINE_STAGE_2_NONE;
4677 
4678 		beginCommandBuffer(vk, *cmdBuf);
4679 
4680 		vk.cmdBindPipeline(*cmdBuf, bindPoint, *m_pipeline);
4681 
4682 		bindDescriptorBuffers(*cmdBuf, bindPoint);
4683 
4684 		// Check if we need any staged descriptor set uploads or push descriptors.
4685 
4686 		for (deUint32 setIndex = 0; setIndex < m_descriptorSetLayouts.size(); ++setIndex)
4687 		{
4688 			const auto& dsl = **m_descriptorSetLayouts[setIndex];
4689 
4690 			if (dsl.usePushDescriptors)
4691 			{
4692 				pushDescriptorSet(*cmdBuf, bindPoint, dsl, setIndex);
4693 			}
4694 			else if (dsl.stagingBufferOffset != OFFSET_UNUSED)
4695 			{
4696 				VkBufferCopy copy {};
4697 				copy.srcOffset = dsl.stagingBufferOffset;
4698 				copy.dstOffset = dsl.bufferOffset;
4699 				copy.size      = dsl.sizeOfLayout;
4700 
4701 				VkBuffer descriptorBuffer = *m_descriptorBuffers[dsl.bufferIndex]->buffer;
4702 
4703 				vk.cmdCopyBuffer(
4704 					*cmdBuf,
4705 					*m_descriptorStagingBuffer.buffer,
4706 					descriptorBuffer,
4707 					1,	// copy regions
4708 					&copy);
4709 
4710 				VkBufferMemoryBarrier2 barrier = initVulkanStructure();
4711 				barrier.srcStageMask		= VK_PIPELINE_STAGE_2_COPY_BIT;
4712 				barrier.srcAccessMask		= VK_ACCESS_2_TRANSFER_WRITE_BIT;
4713 				barrier.dstStageMask		= dstStageMask;
4714 				barrier.dstAccessMask		= VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT;
4715 				barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4716 				barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4717 				barrier.buffer				= descriptorBuffer;
4718 				barrier.offset				= 0;
4719 				barrier.size				= VK_WHOLE_SIZE;
4720 
4721 				VkDependencyInfo depInfo = initVulkanStructure();
4722 				depInfo.bufferMemoryBarrierCount	= 1;
4723 				depInfo.pBufferMemoryBarriers		= &barrier;
4724 
4725 				vk.cmdPipelineBarrier2(*cmdBuf, &depInfo);
4726 			}
4727 		}
4728 
4729 		// Upload image data
4730 
4731 		for (deUint32 setIndex = 0; setIndex < u32(m_descriptorSetLayouts.size()); ++setIndex)
4732 		{
4733 			const auto& dsl = **m_descriptorSetLayouts[setIndex];
4734 
4735 			for (deUint32 bindingIndex = 0; bindingIndex < u32(dsl.bindings.size()); ++bindingIndex)
4736 			{
4737 				const auto& binding = dsl.bindings[bindingIndex];
4738 
4739 				if ((binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
4740 					(binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
4741 					(binding.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ||
4742 					(binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER))
4743 				{
4744 					for (deUint32 arrayIndex = 0; arrayIndex < binding.descriptorCount; ++arrayIndex)
4745 					{
4746 						// Need to upload the image data from a staging buffer
4747 						const auto& dstImage  = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]).image;
4748 						const auto& srcBuffer = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]).buffer;
4749 
4750 						{
4751 							VkImageMemoryBarrier2 barrier = initVulkanStructure();
4752 							barrier.srcStageMask        = VK_PIPELINE_STAGE_2_NONE;
4753 							barrier.srcAccessMask		= VK_ACCESS_2_NONE;
4754 							barrier.dstStageMask		= VK_PIPELINE_STAGE_2_TRANSFER_BIT;
4755 							barrier.dstAccessMask		= VK_ACCESS_2_TRANSFER_WRITE_BIT;
4756 							barrier.oldLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
4757 							barrier.newLayout			= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4758 							barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4759 							barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4760 							barrier.image				= *dstImage.image;
4761 							barrier.subresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
4762 
4763 							VkDependencyInfo depInfo = initVulkanStructure();
4764 							depInfo.imageMemoryBarrierCount	    = 1;
4765 							depInfo.pImageMemoryBarriers		= &barrier;
4766 
4767 							vk.cmdPipelineBarrier2(*cmdBuf, &depInfo);
4768 						}
4769 						{
4770 							VkBufferImageCopy region {};
4771 							// Use default buffer settings
4772 							region.imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1);
4773 							region.imageOffset			= makeOffset3D(0, 0, 0);
4774 							region.imageExtent			= makeExtent3D(m_renderArea.extent.width, m_renderArea.extent.height, 1);
4775 
4776 							vk.cmdCopyBufferToImage(
4777 								*cmdBuf,
4778 								*srcBuffer.buffer,
4779 								*dstImage.image,
4780 								VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4781 								1,	// region count
4782 								&region);
4783 						}
4784 						{
4785 							VkImageMemoryBarrier2 barrier = initVulkanStructure();
4786 							barrier.srcStageMask        = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
4787 							barrier.srcAccessMask		= VK_ACCESS_2_TRANSFER_WRITE_BIT;
4788 							barrier.dstStageMask		= dstStageMaskUp;						// beginning of the shader pipeline
4789 							barrier.dstAccessMask		= VK_ACCESS_2_SHADER_READ_BIT;
4790 							barrier.oldLayout			= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4791 							barrier.newLayout			= dstImage.layout;
4792 							barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4793 							barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4794 							barrier.image				= *dstImage.image;
4795 							barrier.subresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
4796 
4797 							VkDependencyInfo depInfo = initVulkanStructure();
4798 							depInfo.imageMemoryBarrierCount	    = 1;
4799 							depInfo.pImageMemoryBarriers		= &barrier;
4800 
4801 							vk.cmdPipelineBarrier2(*cmdBuf, &depInfo);
4802 						}
4803 					}
4804 				}
4805 				else if (binding.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
4806 				{
4807 					for (deUint32 arrayIndex = 0; arrayIndex < binding.descriptorCount; ++arrayIndex)
4808 					{
4809 						ResourceHolder& resource = (**m_resources[binding.perBindingResourceIndex[arrayIndex]]);
4810 
4811 						resource.rtBlas->build(*m_deviceInterface, *m_device, *cmdBuf);
4812 						resource.rtTlas->build(*m_deviceInterface, *m_device, *cmdBuf);
4813 					}
4814 				}
4815 			}
4816 		}
4817 
4818 		if (m_params.isCompute())
4819 		{
4820 			vk.cmdDispatch(*cmdBuf, 1, 1, 1);
4821 
4822 			{
4823 				auto& resultBuffer = getResultBuffer();
4824 
4825 				VkBufferMemoryBarrier2 barrier = initVulkanStructure();
4826 				barrier.srcStageMask        = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
4827 				barrier.srcAccessMask		= VK_ACCESS_2_SHADER_WRITE_BIT;
4828 				barrier.dstStageMask		= VK_PIPELINE_STAGE_2_HOST_BIT;
4829 				barrier.dstAccessMask		= VK_ACCESS_2_HOST_READ_BIT;
4830 				barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4831 				barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4832 				barrier.buffer				= *resultBuffer.buffer;
4833 				barrier.offset				= 0;
4834 				barrier.size				= VK_WHOLE_SIZE;
4835 
4836 				VkDependencyInfo depInfo = initVulkanStructure();
4837 				depInfo.bufferMemoryBarrierCount	= 1;
4838 				depInfo.pBufferMemoryBarriers		= &barrier;
4839 
4840 				vk.cmdPipelineBarrier2(*cmdBuf, &depInfo);
4841 			}
4842 		}
4843 		else if (m_params.isRayTracing())
4844 		{
4845 			cmdTraceRays(vk,
4846 				*cmdBuf,
4847 				&m_raygenShaderBindingTableRegion,
4848 				&m_missShaderBindingTableRegion,
4849 				&m_hitShaderBindingTableRegion,
4850 				&m_callableShaderBindingTableRegion,
4851 				1, 1, 1);
4852 
4853 			{
4854 				auto& resultBuffer = getResultBuffer();
4855 
4856 				VkBufferMemoryBarrier2 barrier = initVulkanStructure();
4857 				barrier.srcStageMask		= VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR;
4858 				barrier.srcAccessMask		= VK_ACCESS_2_SHADER_WRITE_BIT;
4859 				barrier.dstStageMask		= VK_PIPELINE_STAGE_2_HOST_BIT;
4860 				barrier.dstAccessMask		= VK_ACCESS_2_HOST_READ_BIT;
4861 				barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4862 				barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4863 				barrier.buffer				= *resultBuffer.buffer;
4864 				barrier.offset				= 0;
4865 				barrier.size				= VK_WHOLE_SIZE;
4866 
4867 				VkDependencyInfo depInfo = initVulkanStructure();
4868 				depInfo.bufferMemoryBarrierCount	= 1;
4869 				depInfo.pBufferMemoryBarriers		= &barrier;
4870 
4871 				vk.cmdPipelineBarrier2(*cmdBuf, &depInfo);
4872 			}
4873 		}
4874 		else
4875 		{
4876 			beginRenderPass(vk, *cmdBuf, *m_renderPass, *m_framebuffer, m_renderArea, tcu::Vec4());
4877 
4878 			vk.cmdDraw(*cmdBuf, 6, 1, 0, 0);
4879 
4880 			endRenderPass(vk, *cmdBuf);
4881 
4882 			// Copy the rendered image to a host-visible buffer.
4883 
4884 			{
4885 				VkImageMemoryBarrier2 barrier = initVulkanStructure();
4886 				barrier.srcStageMask        = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
4887 				barrier.srcAccessMask		= VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
4888 				barrier.dstStageMask		= VK_PIPELINE_STAGE_2_TRANSFER_BIT;
4889 				barrier.dstAccessMask		= VK_ACCESS_2_TRANSFER_READ_BIT;
4890 				barrier.oldLayout			= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4891 				barrier.newLayout			= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4892 				barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4893 				barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4894 				barrier.image				= *m_colorImage.image;
4895 				barrier.subresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
4896 
4897 				VkDependencyInfo depInfo = initVulkanStructure();
4898 				depInfo.imageMemoryBarrierCount	    = 1;
4899 				depInfo.pImageMemoryBarriers		= &barrier;
4900 
4901 				vk.cmdPipelineBarrier2(*cmdBuf, &depInfo);
4902 			}
4903 			{
4904 				VkBufferImageCopy region {};
4905 				// Use default buffer settings
4906 				region.imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1);
4907 				region.imageOffset			= makeOffset3D(0, 0, 0);
4908 				region.imageExtent			= m_colorImage.info.extent;
4909 
4910 				vk.cmdCopyImageToBuffer(
4911 					*cmdBuf,
4912 					*m_colorImage.image,
4913 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4914 					*m_colorBuffer.buffer,
4915 					1,	// region count
4916 					&region);
4917 			}
4918 			{
4919 				VkBufferMemoryBarrier2 barrier = initVulkanStructure();
4920 				barrier.srcStageMask        = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
4921 				barrier.srcAccessMask		= VK_ACCESS_2_TRANSFER_WRITE_BIT;
4922 				barrier.dstStageMask		= VK_PIPELINE_STAGE_2_HOST_BIT;
4923 				barrier.dstAccessMask		= VK_ACCESS_2_HOST_READ_BIT;
4924 				barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4925 				barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4926 				barrier.buffer				= *m_colorBuffer.buffer;
4927 				barrier.offset				= 0;
4928 				barrier.size				= VK_WHOLE_SIZE;
4929 
4930 				VkDependencyInfo depInfo = initVulkanStructure();
4931 				depInfo.bufferMemoryBarrierCount	= 1;
4932 				depInfo.pBufferMemoryBarriers		= &barrier;
4933 
4934 				vk.cmdPipelineBarrier2(*cmdBuf, &depInfo);
4935 			}
4936 		}
4937 
4938 		endCommandBuffer(vk, *cmdBuf);
4939 		submitCommandsAndWait(vk, *m_device, m_queue, *cmdBuf);
4940 	}
4941 
4942 	// Verification
4943 	{
4944 		const tcu::UVec4* pResultData = nullptr;
4945 
4946 		if (m_params.isCompute() || m_params.isRayTracing())
4947 		{
4948 			auto& resultBuffer = getResultBuffer();
4949 
4950 			invalidateAlloc(vk, *m_device, *resultBuffer.alloc);
4951 
4952 			pResultData = static_cast<const tcu::UVec4*>(resultBuffer.alloc->getHostPtr());
4953 		}
4954 		else
4955 		{
4956 			pResultData = static_cast<const tcu::UVec4*>(m_colorBuffer.alloc->getHostPtr());
4957 		}
4958 
4959 		const auto	actual	 = pResultData->x();
4960 		deUint32	expected = 0;
4961 
4962 		for (const auto& sb : m_simpleBindings)
4963 		{
4964 			if (!(sb.isResultBuffer || sb.isRayTracingAS))
4965 			{
4966 				if (m_params.variant == TestVariant::MAX)
4967 				{
4968 					// We test enough (image, sampler) pairs to access each one at least once.
4969 					expected = deMaxu32(m_params.samplerBufferBindingCount, m_params.resourceBufferBindingCount);
4970 				}
4971 				else
4972 				{
4973 					// Uniform blocks/buffers check 4 elements per iteration.
4974 					if (sb.type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK)
4975 					{
4976 						expected += ConstChecksPerBuffer * 4;
4977 					}
4978 					else if (sb.type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
4979 					{
4980 						expected += ConstChecksPerBuffer * 4 * sb.count;
4981 					}
4982 					else if ((sb.type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
4983 							 (sb.type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) ||
4984 							 (sb.type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER))
4985 					{
4986 						expected += ConstChecksPerBuffer * sb.count;
4987 					}
4988 					// Samplers are tested implicitly via sampled images
4989 					else if (sb.type != VK_DESCRIPTOR_TYPE_SAMPLER)
4990 					{
4991 						expected += sb.count;
4992 					}
4993 				}
4994 			}
4995 		}
4996 
4997 		if (actual != expected)
4998 		{
4999 			deUint32 badSet			= 0;
5000 			deUint32 badBinding		= 0;
5001 			deUint32 badArrayIndex	= 0;
5002 
5003 			unpackBindingArgs(pResultData->y(), &badSet, &badBinding, &badArrayIndex);
5004 
5005 			std::ostringstream msg;
5006 			msg << "Wrong value in result buffer. Expected (" << expected << ") but got (" << actual << ").";
5007 			msg << " The first wrong binding is (set = " << badSet << ", binding = " << badBinding << ")";
5008 
5009 			if (m_params.variant == TestVariant::MAX)
5010 			{
5011 				deUint32 badSamplerSet		= 0;
5012 				deUint32 badSamplerBinding	= 0;
5013 
5014 				unpackBindingArgs(pResultData->z(), &badSamplerSet, &badSamplerBinding, nullptr);
5015 
5016 				msg << " which used a sampler (set = " << badSamplerSet << ", binding = " << badSamplerBinding << ")";
5017 			}
5018 			else if (badArrayIndex > 0)
5019 			{
5020 				msg << " at array index " << badArrayIndex;
5021 			}
5022 
5023 			msg << ".";
5024 
5025 			return tcu::TestStatus::fail(msg.str());
5026 		}
5027 	}
5028 
5029 	if ((m_params.variant == TestVariant::CAPTURE_REPLAY) && (m_testIteration == 0))
5030 	{
5031 		// The first pass succeeded, continue to the next one where we verify replay.
5032 		++m_testIteration;
5033 
5034 		return tcu::TestStatus::incomplete();
5035 	}
5036 
5037 	return tcu::TestStatus::pass("Pass");
5038 }
5039 
createInstance(Context & context) const5040 TestInstance* DescriptorBufferTestCase::createInstance (Context& context) const
5041 {
5042 	// Currently all tests follow the same basic execution logic.
5043 	return new DescriptorBufferTestInstance(context, m_params, m_simpleBindings);
5044 }
5045 
5046 // This simple tests verifies extension properties against the spec limits.
5047 //
testLimits(Context & context)5048 tcu::TestStatus testLimits(Context& context)
5049 {
5050 #define CHECK_MIN_LIMIT(_struct_, _field_, _limit_) \
5051 	if (_struct_._field_ < _limit_) { TCU_THROW(TestError, #_field_ " is less than " #_limit_); }
5052 
5053 // Max implicitly checks nonzero too
5054 #define CHECK_MAX_LIMIT_NON_ZERO(_struct_, _field_, _limit_) \
5055 	if (_struct_._field_ == 0)      { TCU_THROW(TestError, #_field_ " is 0"); } \
5056 	if (_struct_._field_ > _limit_) { TCU_THROW(TestError, #_field_ " is greater than " #_limit_); }
5057 
5058 #define CHECK_MAX_LIMIT(_struct_, _field_, _limit_) \
5059 	if (_struct_._field_ > _limit_) { TCU_THROW(TestError, #_field_ " is greater than " #_limit_); }
5060 
5061 	if (context.isDeviceFunctionalitySupported("VK_EXT_descriptor_buffer"))
5062 	{
5063 		const auto&		features					= *findStructure<VkPhysicalDeviceDescriptorBufferFeaturesEXT>(&context.getDeviceFeatures2());
5064 		const auto&		props						= *findStructure<VkPhysicalDeviceDescriptorBufferPropertiesEXT>(&context.getDeviceProperties2());
5065 		const bool		hasRT						= context.isDeviceFunctionalitySupported("VK_KHR_ray_tracing_pipeline") ||
5066 													  context.isDeviceFunctionalitySupported("VK_KHR_ray_query") ;
5067 		const size_t	maxResourceDescriptorSize	= std::max(props.storageImageDescriptorSize,
5068 													  std::max(props.sampledImageDescriptorSize,
5069 													  std::max(props.robustUniformTexelBufferDescriptorSize,
5070 													  std::max(props.robustStorageTexelBufferDescriptorSize,
5071 													  std::max(props.robustUniformBufferDescriptorSize,
5072 													  std::max(props.robustStorageBufferDescriptorSize,
5073 													  std::max(props.inputAttachmentDescriptorSize,
5074 													  std::max(props.accelerationStructureDescriptorSize, size_t(0u)))))))));
5075 
5076 		DE_ASSERT(features.descriptorBuffer == VK_TRUE);
5077 
5078 		// Must be queried directly from the physical device, the structure cached in the context has robustness disabled.
5079 		VkPhysicalDeviceFeatures physDeviceFeatures {};
5080 		context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &physDeviceFeatures);
5081 
5082 		if (physDeviceFeatures.robustBufferAccess)
5083 		{
5084 			CHECK_MAX_LIMIT(props, robustUniformTexelBufferDescriptorSize,	64);
5085 			CHECK_MAX_LIMIT(props, robustStorageTexelBufferDescriptorSize,	128);
5086 			CHECK_MAX_LIMIT(props, robustUniformBufferDescriptorSize,		64);
5087 			CHECK_MAX_LIMIT(props, robustStorageBufferDescriptorSize,		128);
5088 		}
5089 
5090 		if (features.descriptorBufferCaptureReplay)
5091 		{
5092 			CHECK_MAX_LIMIT_NON_ZERO(props, bufferCaptureReplayDescriptorDataSize,		64);
5093 			CHECK_MAX_LIMIT_NON_ZERO(props, imageCaptureReplayDescriptorDataSize,		64);
5094 			CHECK_MAX_LIMIT_NON_ZERO(props, imageViewCaptureReplayDescriptorDataSize,	64);
5095 			CHECK_MAX_LIMIT_NON_ZERO(props, samplerCaptureReplayDescriptorDataSize,		64);
5096 
5097 			if (hasRT)
5098 			{
5099 				CHECK_MAX_LIMIT_NON_ZERO(props, accelerationStructureCaptureReplayDescriptorDataSize,	64);
5100 			}
5101 		}
5102 
5103 		if (hasRT)
5104 		{
5105 			CHECK_MAX_LIMIT_NON_ZERO(props, accelerationStructureDescriptorSize,	64);
5106 		}
5107 
5108 		CHECK_MAX_LIMIT_NON_ZERO(props, descriptorBufferOffsetAlignment,	256);
5109 
5110 		CHECK_MIN_LIMIT(props, maxDescriptorBufferBindings,				3);
5111 		CHECK_MIN_LIMIT(props, maxResourceDescriptorBufferBindings,		1);
5112 		CHECK_MIN_LIMIT(props, maxSamplerDescriptorBufferBindings,		1);
5113 		CHECK_MIN_LIMIT(props, maxEmbeddedImmutableSamplerBindings,		1);
5114 		CHECK_MIN_LIMIT(props, maxEmbeddedImmutableSamplers,			2032);
5115 
5116 		CHECK_MAX_LIMIT_NON_ZERO(props, samplerDescriptorSize,				64);
5117 		CHECK_MAX_LIMIT_NON_ZERO(props, combinedImageSamplerDescriptorSize,	128);
5118 		CHECK_MAX_LIMIT_NON_ZERO(props, sampledImageDescriptorSize,			64);
5119 		CHECK_MAX_LIMIT_NON_ZERO(props, storageImageDescriptorSize,			128);
5120 		CHECK_MAX_LIMIT_NON_ZERO(props, uniformTexelBufferDescriptorSize,	64);
5121 		CHECK_MAX_LIMIT_NON_ZERO(props, storageTexelBufferDescriptorSize,	128);
5122 		CHECK_MAX_LIMIT_NON_ZERO(props, uniformBufferDescriptorSize,		64);
5123 		CHECK_MAX_LIMIT_NON_ZERO(props, storageBufferDescriptorSize,		128);
5124 		CHECK_MAX_LIMIT(props, inputAttachmentDescriptorSize,				64);
5125 
5126 		CHECK_MIN_LIMIT(props, maxSamplerDescriptorBufferRange,				((1u << 11) * props.samplerDescriptorSize));
5127 		CHECK_MIN_LIMIT(props, maxResourceDescriptorBufferRange,			(((1u << 20) - (1u << 15)) * maxResourceDescriptorSize));
5128 		CHECK_MIN_LIMIT(props, samplerDescriptorBufferAddressSpaceSize,		(1u << 27));
5129 		CHECK_MIN_LIMIT(props, resourceDescriptorBufferAddressSpaceSize,	(1u << 27));
5130 		CHECK_MIN_LIMIT(props, descriptorBufferAddressSpaceSize,			(1u << 27));
5131 
5132 		// The following requirement ensures that for split combined image sampler arrays:
5133 		// - there's no unnecessary padding at the end, or
5134 		// - there's no risk of overrun (if somehow the sum of image and sampler was greater).
5135 
5136 		if ((props.combinedImageSamplerDescriptorSingleArray == VK_FALSE) &&
5137 			((props.sampledImageDescriptorSize + props.samplerDescriptorSize) != props.combinedImageSamplerDescriptorSize))
5138 		{
5139 			return tcu::TestStatus::fail("For combinedImageSamplerDescriptorSingleArray, it is expected that the sampled image size "
5140 				"and the sampler size add up to combinedImageSamplerDescriptorSize.");
5141 		}
5142 	}
5143 	else
5144 	{
5145 		TCU_THROW(NotSupportedError, "VK_EXT_descriptor_buffer is not supported");
5146 	}
5147 
5148 	return tcu::TestStatus::pass("Pass");
5149 
5150 #undef CHECK_MIN_LIMIT
5151 #undef CHECK_MAX_LIMIT
5152 #undef CHECK_MAX_LIMIT_NON_ZERO
5153 }
5154 
populateDescriptorBufferTests(tcu::TestCaseGroup * topGroup)5155 void populateDescriptorBufferTests (tcu::TestCaseGroup* topGroup)
5156 {
5157 	tcu::TestContext&	testCtx		= topGroup->getTestContext();
5158 	const uint32_t		baseSeed	= static_cast<deUint32>(testCtx.getCommandLine().getBaseSeed());;
5159 	std::string			caseName;
5160 
5161 	const VkQueueFlagBits choiceQueues[] {
5162 		VK_QUEUE_GRAPHICS_BIT,
5163 		VK_QUEUE_COMPUTE_BIT,
5164 	};
5165 
5166 	const VkShaderStageFlagBits choiceStages[] {
5167 		VK_SHADER_STAGE_VERTEX_BIT,
5168 		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
5169 		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
5170 		VK_SHADER_STAGE_GEOMETRY_BIT,
5171 		VK_SHADER_STAGE_FRAGMENT_BIT,
5172 		VK_SHADER_STAGE_COMPUTE_BIT,
5173 		VK_SHADER_STAGE_RAYGEN_BIT_KHR,
5174 		VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
5175 		VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
5176 		VK_SHADER_STAGE_MISS_BIT_KHR,
5177 		VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
5178 		VK_SHADER_STAGE_CALLABLE_BIT_KHR,
5179 	};
5180 
5181 	{
5182 		MovePtr<tcu::TestCaseGroup> subGroup(new tcu::TestCaseGroup(testCtx, "basic", "Basic tests"));
5183 
5184 		addFunctionCase(subGroup.get(), "limits", "Check basic device properties and limits", testLimits);
5185 
5186 		topGroup->addChild(subGroup.release());
5187 	}
5188 
5189 	{
5190 		//
5191 		// Basic single descriptor cases -- a sanity check.
5192 		//
5193 		MovePtr<tcu::TestCaseGroup>	subGroup		(new tcu::TestCaseGroup(testCtx, "single", "Single binding tests"));
5194 		const uint32_t				subGroupHash	= baseSeed ^ deStringHash(subGroup->getName());
5195 
5196 		// VK_DESCRIPTOR_TYPE_SAMPLER is tested implicitly by sampled image case.
5197 		// *_BUFFER_DYNAMIC are not allowed with descriptor buffers.
5198 		//
5199 		const VkDescriptorType choiceDescriptors[] {
5200 			VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
5201 			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
5202 			VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
5203 			VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
5204 			VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
5205 			VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
5206 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
5207 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
5208 			VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK,
5209 			VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
5210 		};
5211 
5212 		for (auto pQueue = choiceQueues; pQueue < DE_ARRAY_END(choiceQueues); ++pQueue)
5213 		for (auto pStage = choiceStages; pStage < DE_ARRAY_END(choiceStages); ++pStage)
5214 		for (auto pDescriptor = choiceDescriptors; pDescriptor < DE_ARRAY_END(choiceDescriptors); ++pDescriptor)
5215 		{
5216 			if ((*pQueue == VK_QUEUE_COMPUTE_BIT) && (*pStage != VK_SHADER_STAGE_COMPUTE_BIT))
5217 			{
5218 				// Compute queue can only use compute shaders.
5219 				continue;
5220 			}
5221 
5222 			if ((*pDescriptor == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) && (*pStage != VK_SHADER_STAGE_FRAGMENT_BIT))
5223 			{
5224 				// Subpass loads are only valid in fragment stage.
5225 				continue;
5226 			}
5227 
5228 			TestParams params {};
5229 			params.variant				= TestVariant::SINGLE;
5230 			params.subcase				= SubCase::NONE;
5231 			params.stage				= *pStage;
5232 			params.queue				= *pQueue;
5233 			params.descriptor			= *pDescriptor;
5234 			params.bufferBindingCount	= 1;
5235 			params.setsPerBuffer		= 1;
5236 
5237 			subGroup->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupHash), "", params));
5238 		}
5239 
5240 		topGroup->addChild(subGroup.release());
5241 	}
5242 
5243 	{
5244 		//
5245 		// More complex cases. Multiple sets and bindings per buffer. Immutable samplers.
5246 		//
5247 		MovePtr<tcu::TestCaseGroup> subGroup		(new tcu::TestCaseGroup(testCtx, "multiple", "Multiple bindings tests"));
5248 		const uint32_t				subGroupHash	= baseSeed ^ deStringHash(subGroup->getName());
5249 		const VkShaderStageFlags	longTestStages	= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
5250 
5251 		const struct {
5252 			deUint32 bufferBindingCount;
5253 			deUint32 setsPerBuffer;
5254 		} caseOptions[] = {
5255 			{  1,  1 },
5256 			{  1,  3 },
5257 			{  2,  4 },
5258 			{  3,  1 },		// 3 buffer bindings is spec minimum
5259 			{  8,  1 },
5260 			{ 16,  1 },
5261 			{ 32,  1 },
5262 		};
5263 
5264 		for (auto pQueue = choiceQueues; pQueue < DE_ARRAY_END(choiceQueues); ++pQueue)
5265 		for (auto pStage = choiceStages; pStage < DE_ARRAY_END(choiceStages); ++pStage)
5266 		for (auto pOptions = caseOptions; pOptions < DE_ARRAY_END(caseOptions); ++pOptions)
5267 		{
5268 			if ((*pQueue == VK_QUEUE_COMPUTE_BIT) && (*pStage != VK_SHADER_STAGE_COMPUTE_BIT))
5269 			{
5270 				// Compute queue can only use compute shaders.
5271 				continue;
5272 			}
5273 
5274 			if (pOptions->bufferBindingCount >= 16 && ((*pStage) & longTestStages) == 0)
5275 			{
5276 				// Allow long tests for certain stages only, skip on rest stages
5277 				continue;
5278 			}
5279 
5280 			TestParams params {};
5281 			params.variant						= TestVariant::MULTIPLE;
5282 			params.subcase						= SubCase::NONE;
5283 			params.stage						= *pStage;
5284 			params.queue						= *pQueue;
5285 			params.bufferBindingCount			= pOptions->bufferBindingCount;
5286 			params.samplerBufferBindingCount	= pOptions->bufferBindingCount;
5287 			params.resourceBufferBindingCount	= pOptions->bufferBindingCount;
5288 			params.setsPerBuffer				= pOptions->setsPerBuffer;
5289 			params.descriptor					= VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; // Optional, will be tested if supported
5290 
5291 			subGroup->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupHash), "", params));
5292 
5293 			if ((pOptions->setsPerBuffer != 1) && (pOptions->bufferBindingCount < 4))
5294 			{
5295 				// For the smaller binding counts add a subcase with immutable samplers.
5296 
5297 				params.subcase = SubCase::IMMUTABLE_SAMPLERS;
5298 
5299 				subGroup->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupHash), "", params));
5300 			}
5301 		}
5302 
5303 		topGroup->addChild(subGroup.release());
5304 	}
5305 
5306 	{
5307 		//
5308 		// These cases exercise buffers of single usage (samplers only and resources only) and tries to use
5309 		// all available buffer bindings.
5310 		//
5311 		MovePtr<tcu::TestCaseGroup>	subGroup		(new tcu::TestCaseGroup(testCtx, "max", "Max sampler/resource bindings tests"));
5312 		const uint32_t				subGroupHash	= baseSeed ^ deStringHash(subGroup->getName());
5313 
5314 		const struct {
5315 			deUint32 samplerBufferBindingCount;
5316 			deUint32 resourceBufferBindingCount;
5317 		} caseOptions[] = {
5318 			{  1,   1 },
5319 			{  2,   2 },
5320 			{  4,   4 },
5321 			{  8,   8 },
5322 			{ 16,  16 },
5323 			{  1,   7 },
5324 			{  1,  15 },
5325 			{  1,  31 },
5326 			{  7,   1 },
5327 			{ 15,   1 },
5328 			{ 31,   1 },
5329 		};
5330 
5331 		for (auto pQueue = choiceQueues; pQueue < DE_ARRAY_END(choiceQueues); ++pQueue)
5332 		for (auto pStage = choiceStages; pStage < DE_ARRAY_END(choiceStages); ++pStage)
5333 		for (auto pOptions = caseOptions; pOptions < DE_ARRAY_END(caseOptions); ++pOptions)
5334 		{
5335 			if ((*pQueue == VK_QUEUE_COMPUTE_BIT) && (*pStage != VK_SHADER_STAGE_COMPUTE_BIT))
5336 			{
5337 				// Compute queue can only use compute shaders.
5338 				continue;
5339 			}
5340 
5341 			if (isAllRayTracingStages(*pStage) && (pOptions->samplerBufferBindingCount > 15 || pOptions->resourceBufferBindingCount > 15))
5342 			{
5343 				// Limit ray tracing stages
5344 				continue;
5345 			}
5346 
5347 			TestParams params {};
5348 			params.variant					  = TestVariant::MAX;
5349 			params.subcase					  = SubCase::NONE;
5350 			params.stage					  = *pStage;
5351 			params.queue					  = *pQueue;
5352 			params.samplerBufferBindingCount  = pOptions->samplerBufferBindingCount;
5353 			params.resourceBufferBindingCount = pOptions->resourceBufferBindingCount;
5354 			params.bufferBindingCount		  = pOptions->samplerBufferBindingCount + pOptions->resourceBufferBindingCount;
5355 			params.setsPerBuffer			  = 1;
5356 			params.descriptor				  = VK_DESCRIPTOR_TYPE_MAX_ENUM;
5357 
5358 			subGroup->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupHash), "", params));
5359 		}
5360 
5361 		topGroup->addChild(subGroup.release());
5362 	}
5363 
5364 	{
5365 		//
5366 		// Check embedded immutable sampler buffers/bindings.
5367 		//
5368 		MovePtr<tcu::TestCaseGroup>	subGroup		(new tcu::TestCaseGroup(testCtx, "embedded_imm_samplers", "Max embedded immutable samplers tests"));
5369 		const uint32_t				subGroupHash	= baseSeed ^ deStringHash(subGroup->getName());
5370 
5371 		const struct {
5372 			deUint32 bufferBindingCount;
5373 			deUint32 samplersPerBuffer;
5374 		} caseOptions[] = {
5375 			{  1,  1 },
5376 			{  1,  2 },
5377 			{  1,  4 },
5378 			{  1,  8 },
5379 			{  1, 16 },
5380 			{  2,  1 },
5381 			{  2,  2 },
5382 			{  3,  1 },
5383 			{  3,  3 },
5384 			{  8,  1 },
5385 			{  8,  4 },
5386 		};
5387 
5388 		for (auto pQueue = choiceQueues; pQueue < DE_ARRAY_END(choiceQueues); ++pQueue)
5389 		for (auto pStage = choiceStages; pStage < DE_ARRAY_END(choiceStages); ++pStage)
5390 		for (auto pOptions = caseOptions; pOptions < DE_ARRAY_END(caseOptions); ++pOptions)
5391 		{
5392 			if ((*pQueue == VK_QUEUE_COMPUTE_BIT) && (*pStage != VK_SHADER_STAGE_COMPUTE_BIT))
5393 			{
5394 				// Compute queue can only use compute shaders.
5395 				continue;
5396 			}
5397 
5398 			TestParams params {};
5399 			params.variant										= TestVariant::EMBEDDED_IMMUTABLE_SAMPLERS;
5400 			params.subcase										= SubCase::NONE;
5401 			params.stage										= *pStage;
5402 			params.queue										= *pQueue;
5403 			params.bufferBindingCount							= pOptions->bufferBindingCount + 1;
5404 			params.samplerBufferBindingCount					= pOptions->bufferBindingCount;
5405 			params.resourceBufferBindingCount					= 1;
5406 			params.setsPerBuffer								= 1;
5407 			params.embeddedImmutableSamplerBufferBindingCount	= pOptions->bufferBindingCount;
5408 			params.embeddedImmutableSamplersPerBuffer			= pOptions->samplersPerBuffer;
5409 			params.descriptor									= VK_DESCRIPTOR_TYPE_MAX_ENUM;
5410 
5411 			subGroup->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupHash), "", params));
5412 		}
5413 
5414 		topGroup->addChild(subGroup.release());
5415 	}
5416 
5417 	{
5418 		//
5419 		// Check push descriptors and push descriptors with template updates
5420 		//
5421 		MovePtr<tcu::TestCaseGroup> subGroupPush				(new tcu::TestCaseGroup(testCtx, "push_descriptor", "Use push descriptors in addition to descriptor buffer"));
5422 		MovePtr<tcu::TestCaseGroup> subGroupPushTemplate		(new tcu::TestCaseGroup(testCtx, "push_template", "Use descriptor update template with push descriptors in addition to descriptor buffer"));
5423 		const uint32_t				subGroupPushHash			= baseSeed ^ deStringHash(subGroupPush->getName());
5424 		const uint32_t				subGroupPushTemplateHash	= baseSeed ^ deStringHash(subGroupPushTemplate->getName());
5425 
5426 		const struct {
5427 			deUint32 pushDescriptorSetIndex;
5428 			deUint32 bufferBindingCount;
5429 
5430 			// The total number of descriptor sets will be bufferBindingCount + 1, where the additional set is used for push descriptors.
5431 
5432 		} caseOptions[] = {
5433 			{  0,  0 },		// Only push descriptors
5434 			{  0,  1 },
5435 			{  0,  3 },
5436 			{  1,  1 },
5437 			{  0,  2 },
5438 			{  1,  2 },
5439 			{  2,  2 },		// index = 2 means 3 sets, where the first two are used with descriptor buffer and the last with push descriptors
5440 			{  3,  3 },
5441 		};
5442 
5443 		for (auto pQueue = choiceQueues; pQueue < DE_ARRAY_END(choiceQueues); ++pQueue)
5444 		for (auto pStage = choiceStages; pStage < DE_ARRAY_END(choiceStages); ++pStage)
5445 		for (auto pOptions = caseOptions; pOptions < DE_ARRAY_END(caseOptions); ++pOptions)
5446 		{
5447 			if ((*pQueue == VK_QUEUE_COMPUTE_BIT) && (*pStage != VK_SHADER_STAGE_COMPUTE_BIT))
5448 			{
5449 				// Compute queue can only use compute shaders.
5450 				continue;
5451 			}
5452 
5453 			TestParams params {};
5454 			params.variant						= TestVariant::PUSH_DESCRIPTOR;
5455 			params.subcase						= SubCase::NONE;
5456 			params.stage						= *pStage;
5457 			params.queue						= *pQueue;
5458 			params.bufferBindingCount			= pOptions->bufferBindingCount;
5459 			params.samplerBufferBindingCount	= pOptions->bufferBindingCount;
5460 			params.resourceBufferBindingCount	= pOptions->bufferBindingCount;
5461 			params.setsPerBuffer				= 1;
5462 			params.pushDescriptorSetIndex		= pOptions->pushDescriptorSetIndex;
5463 			params.descriptor					= VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; // Optional, will be tested if supported
5464 
5465 			subGroupPush->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupPushHash), "", params));
5466 
5467 			if (pOptions->bufferBindingCount < 2)
5468 			{
5469 				TestParams paramsSingleBuffer = params;
5470 
5471 				paramsSingleBuffer.subcase = SubCase::SINGLE_BUFFER;
5472 
5473 				subGroupPush->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(paramsSingleBuffer, subGroupPushHash), "", paramsSingleBuffer));
5474 			}
5475 
5476 			params.variant = TestVariant::PUSH_TEMPLATE;
5477 
5478 			subGroupPushTemplate->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupPushTemplateHash), "", params));
5479 		}
5480 
5481 		topGroup->addChild(subGroupPush.release());
5482 		topGroup->addChild(subGroupPushTemplate.release());
5483 	}
5484 
5485 	{
5486 		//
5487 		// Robustness tests
5488 		//
5489 		MovePtr<tcu::TestCaseGroup> subGroup					(new tcu::TestCaseGroup(testCtx, "robust", "Robustness tests"));
5490 		MovePtr<tcu::TestCaseGroup> subGroupBuffer				(new tcu::TestCaseGroup(testCtx, "buffer_access", "Robust buffer access"));
5491 		MovePtr<tcu::TestCaseGroup> subGroupNullDescriptor		(new tcu::TestCaseGroup(testCtx, "null_descriptor", "Null descriptor"));
5492 		const uint32_t				subGroupBufferHash			= baseSeed ^ deStringHash(subGroupBuffer->getName());
5493 		const uint32_t				subGroupNullDescriptorHash	= baseSeed ^ deStringHash(subGroupNullDescriptor->getName());
5494 
5495 		// Robust buffer access:
5496 		// This test will fill the buffers with zeros and always expect to read zero values back (in and out of bounds).
5497 
5498 		// Null descriptor cases:
5499 		// For each test, one of these descriptors will have its buffer/imageView/etc. set to null handle.
5500 		// Reads done through a null descriptor are expected to return zeros.
5501 		//
5502 		const VkDescriptorType choiceNullDescriptors[] {
5503 			VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
5504 			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
5505 			VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
5506 			VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
5507 			VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
5508 			VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
5509 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
5510 			VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
5511 		};
5512 
5513 		for (auto pQueue = choiceQueues; pQueue < DE_ARRAY_END(choiceQueues); ++pQueue)
5514 		for (auto pStage = choiceStages; pStage < DE_ARRAY_END(choiceStages); ++pStage)
5515 		{
5516 			if ((*pQueue == VK_QUEUE_COMPUTE_BIT) && (*pStage != VK_SHADER_STAGE_COMPUTE_BIT))
5517 			{
5518 				// Compute queue can only use compute shaders.
5519 				continue;
5520 			}
5521 
5522 			TestParams params {};
5523 			params.variant				= TestVariant::ROBUST_BUFFER_ACCESS;
5524 			params.stage				= *pStage;
5525 			params.queue				= *pQueue;
5526 			params.bufferBindingCount	= 1;
5527 			params.setsPerBuffer		= 1;
5528 
5529 			subGroupBuffer->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupBufferHash), "", params));
5530 
5531 			for (auto pDescriptor = choiceNullDescriptors; pDescriptor < DE_ARRAY_END(choiceNullDescriptors); ++pDescriptor)
5532 			{
5533 				if ((*pDescriptor == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) && (*pStage != VK_SHADER_STAGE_FRAGMENT_BIT))
5534 				{
5535 					// Subpass loads are only valid in fragment stage.
5536 					continue;
5537 				}
5538 
5539 				params.variant		= TestVariant::ROBUST_NULL_DESCRIPTOR;
5540 				params.descriptor	= *pDescriptor;
5541 
5542 				subGroupNullDescriptor->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupNullDescriptorHash), "", params));
5543 			}
5544 		}
5545 
5546 		subGroup->addChild(subGroupBuffer.release());
5547 		subGroup->addChild(subGroupNullDescriptor.release());
5548 		topGroup->addChild(subGroup.release());
5549 	}
5550 
5551 	{
5552 		//
5553 		// Capture and replay
5554 		//
5555 		MovePtr<tcu::TestCaseGroup>	subGroup		(new tcu::TestCaseGroup(testCtx, "capture_replay", "Capture and replay tests"));
5556 		const uint32_t				subGroupHash	= baseSeed ^ deStringHash(subGroup->getName());
5557 
5558 		const VkDescriptorType choiceDescriptors[] {
5559 			VK_DESCRIPTOR_TYPE_SAMPLER,
5560 			VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	// both sampler and image are captured
5561 			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
5562 			VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
5563 			VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
5564 			VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
5565 			VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
5566 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
5567 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
5568 			VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
5569 		};
5570 
5571 		for (auto pQueue = choiceQueues; pQueue < DE_ARRAY_END(choiceQueues); ++pQueue)
5572 		for (auto pStage = choiceStages; pStage < DE_ARRAY_END(choiceStages); ++pStage)
5573 		for (auto pDescriptor = choiceDescriptors; pDescriptor < DE_ARRAY_END(choiceDescriptors); ++pDescriptor)
5574 		{
5575 			if ((*pQueue == VK_QUEUE_COMPUTE_BIT) && (*pStage != VK_SHADER_STAGE_COMPUTE_BIT))
5576 			{
5577 				// Compute queue can only use compute shaders.
5578 				continue;
5579 			}
5580 
5581 			if ((*pDescriptor == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) && (*pStage != VK_SHADER_STAGE_FRAGMENT_BIT))
5582 			{
5583 				// Subpass loads are only valid in fragment stage.
5584 				continue;
5585 			}
5586 
5587 			TestParams params {};
5588 			params.variant				= TestVariant::CAPTURE_REPLAY;
5589 			params.subcase				= SubCase::NONE;
5590 			params.stage				= *pStage;
5591 			params.queue				= *pQueue;
5592 			params.descriptor			= *pDescriptor;
5593 			params.bufferBindingCount	= 1;
5594 			params.setsPerBuffer		= 1;
5595 
5596 			subGroup->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupHash), "", params));
5597 
5598 			if ((*pDescriptor == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
5599 				(*pDescriptor == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
5600 				(*pDescriptor == VK_DESCRIPTOR_TYPE_SAMPLER))
5601 			{
5602 				params.subcase = SubCase::CAPTURE_REPLAY_CUSTOM_BORDER_COLOR;
5603 
5604 				subGroup->addChild(new DescriptorBufferTestCase(testCtx, getCaseNameUpdateHash(params, subGroupHash), "", params));
5605 			}
5606 		}
5607 
5608 		topGroup->addChild(subGroup.release());
5609 	}
5610 
5611 }
5612 
5613 } // anonymous
5614 
createDescriptorBufferTests(tcu::TestContext & testCtx)5615 tcu::TestCaseGroup* createDescriptorBufferTests (tcu::TestContext& testCtx)
5616 {
5617 	return createTestGroup(testCtx, "descriptor_buffer", "Descriptor buffer tests.", populateDescriptorBufferTests);
5618 }
5619 
5620 } // BindingModel
5621 } // vkt
5622