• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  * Copyright (c) 2020 Valve Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *	  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Ray Tracing barrier tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktRayTracingBarrierTests.hpp"
26 #include "vktTestCase.hpp"
27 
28 #include "vkDefs.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkRayTracingUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBufferWithMemory.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 
39 #include "deUniquePtr.hpp"
40 
41 #include <string>
42 #include <sstream>
43 #include <memory>
44 #include <numeric>
45 #include <vector>
46 #include <algorithm>
47 
48 namespace vkt
49 {
50 namespace RayTracing
51 {
52 
53 namespace
54 {
55 
56 using namespace vk;
57 
58 constexpr deUint32				kBufferElements	= 1024u;
59 constexpr deUint32				kBufferSize		= kBufferElements * static_cast<deUint32>(sizeof(tcu::UVec4));	// std140
60 constexpr deUint32				kBufferSize430	= kBufferElements * static_cast<deUint32>(sizeof(deUint32));	// std430
61 constexpr deUint32				kValuesOffset	= 2048u;
62 constexpr deUint32				kImageDim		= 32u;					// So that kImageDim*kImageDim == kBufferElements.
63 constexpr VkFormat				kImageFormat	= VK_FORMAT_R32_UINT;	// So that each pixel has the same size as a deUint32.
64 const auto						kImageExtent	= makeExtent3D(kImageDim, kImageDim, 1u);
65 const std::vector<tcu::Vec4>	kFullScreenQuad	=
66 {
67 	tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
68 	tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
69 	tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
70 	tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
71 	tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
72 	tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
73 };
74 
75 
76 enum class Stage
77 {
78 	HOST = 0,
79 	TRANSFER,
80 	RAYGEN,
81 	INTERSECT,
82 	ANY_HIT,
83 	CLOSEST_HIT,
84 	MISS,
85 	CALLABLE,
86 	COMPUTE,
87 	FRAGMENT,
88 };
89 
getOptimalReadLayout(Stage stage)90 VkImageLayout getOptimalReadLayout (Stage stage)
91 {
92 	VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
93 
94 	switch (stage)
95 	{
96 	case Stage::HOST:
97 		break; // Images will not be read directly from the host.
98 	case Stage::TRANSFER:
99 		layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
100 		break;
101 	case Stage::RAYGEN:
102 	case Stage::INTERSECT:
103 	case Stage::ANY_HIT:
104 	case Stage::CLOSEST_HIT:
105 	case Stage::MISS:
106 	case Stage::CALLABLE:
107 	case Stage::COMPUTE:
108 	case Stage::FRAGMENT:
109 		layout = VK_IMAGE_LAYOUT_GENERAL;
110 		break;
111 	default:
112 		DE_ASSERT(false);
113 		break;
114 	}
115 
116 	return layout;
117 }
118 
getPipelineStage(Stage stage)119 VkPipelineStageFlagBits getPipelineStage (Stage stage)
120 {
121 	VkPipelineStageFlagBits bits = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM;
122 
123 	switch (stage)
124 	{
125 	case Stage::HOST:
126 		bits = VK_PIPELINE_STAGE_HOST_BIT;
127 		break;
128 	case Stage::TRANSFER:
129 		bits = VK_PIPELINE_STAGE_TRANSFER_BIT;
130 		break;
131 	case Stage::RAYGEN:
132 	case Stage::INTERSECT:
133 	case Stage::ANY_HIT:
134 	case Stage::CLOSEST_HIT:
135 	case Stage::MISS:
136 	case Stage::CALLABLE:
137 		bits = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
138 		break;
139 	case Stage::COMPUTE:
140 		bits = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
141 		break;
142 	case Stage::FRAGMENT:
143 		bits = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
144 		break;
145 	default:
146 		DE_ASSERT(false);
147 		break;
148 	}
149 
150 	return bits;
151 }
152 
getWriterAccessFlag(Stage stage)153 VkAccessFlagBits getWriterAccessFlag (Stage stage)
154 {
155 	VkAccessFlagBits bits = VK_ACCESS_FLAG_BITS_MAX_ENUM;
156 
157 	switch (stage)
158 	{
159 	case Stage::HOST:
160 		bits = VK_ACCESS_HOST_WRITE_BIT;
161 		break;
162 	case Stage::TRANSFER:
163 		bits = VK_ACCESS_TRANSFER_WRITE_BIT;
164 		break;
165 	case Stage::RAYGEN:
166 	case Stage::INTERSECT:
167 	case Stage::ANY_HIT:
168 	case Stage::CLOSEST_HIT:
169 	case Stage::MISS:
170 	case Stage::CALLABLE:
171 	case Stage::COMPUTE:
172 	case Stage::FRAGMENT:
173 		bits = VK_ACCESS_SHADER_WRITE_BIT;
174 		break;
175 	default:
176 		DE_ASSERT(false);
177 		break;
178 	}
179 
180 	return bits;
181 }
182 
getReaderAccessFlag(Stage stage,VkDescriptorType resourceType)183 VkAccessFlagBits getReaderAccessFlag (Stage stage, VkDescriptorType resourceType)
184 {
185 	VkAccessFlagBits bits = VK_ACCESS_FLAG_BITS_MAX_ENUM;
186 
187 	switch (stage)
188 	{
189 	case Stage::HOST:
190 		bits = VK_ACCESS_HOST_READ_BIT;
191 		break;
192 	case Stage::TRANSFER:
193 		bits = VK_ACCESS_TRANSFER_READ_BIT;
194 		break;
195 	case Stage::RAYGEN:
196 	case Stage::INTERSECT:
197 	case Stage::ANY_HIT:
198 	case Stage::CLOSEST_HIT:
199 	case Stage::MISS:
200 	case Stage::CALLABLE:
201 	case Stage::COMPUTE:
202 	case Stage::FRAGMENT:
203 		bits = ((resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ? VK_ACCESS_UNIFORM_READ_BIT : VK_ACCESS_SHADER_READ_BIT);
204 		break;
205 	default:
206 		DE_ASSERT(false);
207 		break;
208 	}
209 
210 	return bits;
211 }
212 
213 // Translate a stage to the corresponding single stage flag.
getShaderStageFlagBits(Stage stage)214 VkShaderStageFlagBits getShaderStageFlagBits (Stage stage)
215 {
216 	VkShaderStageFlagBits bits = VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM;
217 
218 	switch (stage)
219 	{
220 	case Stage::RAYGEN:			bits = VK_SHADER_STAGE_RAYGEN_BIT_KHR;			break;
221 	case Stage::INTERSECT:		bits = VK_SHADER_STAGE_INTERSECTION_BIT_KHR;	break;
222 	case Stage::ANY_HIT:		bits = VK_SHADER_STAGE_ANY_HIT_BIT_KHR;			break;
223 	case Stage::CLOSEST_HIT:	bits = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;		break;
224 	case Stage::MISS:			bits = VK_SHADER_STAGE_MISS_BIT_KHR;			break;
225 	case Stage::CALLABLE:		bits = VK_SHADER_STAGE_CALLABLE_BIT_KHR;		break;
226 	case Stage::COMPUTE:		bits = VK_SHADER_STAGE_COMPUTE_BIT;				break;
227 	case Stage::FRAGMENT:		bits = VK_SHADER_STAGE_FRAGMENT_BIT;			break;
228 	default:					DE_ASSERT(false);								break;
229 	}
230 
231 	return bits;
232 }
233 
234 // Gets shader stage flags that will be used when choosing a given stage.
getStageFlags(Stage stage)235 VkShaderStageFlags getStageFlags (Stage stage)
236 {
237 	VkShaderStageFlags flags = 0u;
238 
239 	switch (stage)
240 	{
241 	case Stage::HOST:			break;
242 	case Stage::TRANSFER:		break;
243 	case Stage::RAYGEN:			flags |= (VK_SHADER_STAGE_RAYGEN_BIT_KHR);											break;
244 	case Stage::INTERSECT:		flags |= (VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR);	break;
245 	case Stage::ANY_HIT:		flags |= (VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);		break;
246 	case Stage::CLOSEST_HIT:	flags |= (VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);	break;
247 	case Stage::MISS:			flags |= (VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR);			break;
248 	case Stage::CALLABLE:		flags |= (VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR);		break;
249 	case Stage::COMPUTE:		flags |= (VK_SHADER_STAGE_COMPUTE_BIT);												break;
250 	case Stage::FRAGMENT:		flags |= (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);				break;
251 	default:					DE_ASSERT(false);																	break;
252 	}
253 
254 	return flags;
255 }
256 
isRayTracingStage(Stage stage)257 bool isRayTracingStage (Stage stage)
258 {
259 	bool isRT = false;
260 
261 	switch (stage)
262 	{
263 	case Stage::HOST:
264 	case Stage::TRANSFER:
265 	case Stage::COMPUTE:
266 	case Stage::FRAGMENT:
267 		break;
268 
269 	case Stage::RAYGEN:
270 	case Stage::INTERSECT:
271 	case Stage::ANY_HIT:
272 	case Stage::CLOSEST_HIT:
273 	case Stage::MISS:
274 	case Stage::CALLABLE:
275 		isRT = true;
276 		break;
277 
278 	default:
279 		DE_ASSERT(false);
280 		break;
281 	}
282 
283 	return isRT;
284 }
285 
286 enum class BarrierType
287 {
288 	GENERAL		= 0,
289 	SPECIFIC	= 1,
290 };
291 
292 struct TestParams
293 {
294 	VkDescriptorType	resourceType;
295 	Stage				writerStage;
296 	Stage				readerStage;
297 	BarrierType			barrierType;
298 
TestParamsvkt::RayTracing::__anon2c1cb5820111::TestParams299 	TestParams (VkDescriptorType resourceType_, Stage writerStage_, Stage readerStage_, BarrierType barrierType_)
300 		: resourceType	(resourceType_)
301 		, writerStage	(writerStage_)
302 		, readerStage	(readerStage_)
303 		, barrierType	(barrierType_)
304 	{
305 		DE_ASSERT(resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
306 				  resourceType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
307 				  resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
308 	}
309 };
310 
resourceNeedsHostVisibleMemory(const TestParams & params)311 bool resourceNeedsHostVisibleMemory (const TestParams& params)
312 {
313 	return (params.writerStage == Stage::HOST || params.readerStage == Stage::HOST);
314 }
315 
needsAccelerationStructure(Stage stage)316 bool needsAccelerationStructure (Stage stage)
317 {
318 	bool needed;
319 
320 	switch (stage)
321 	{
322 	case Stage::INTERSECT:
323 	case Stage::ANY_HIT:
324 	case Stage::CLOSEST_HIT:
325 	case Stage::MISS:
326 	case Stage::CALLABLE:
327 		needed = true;
328 		break;
329 	default:
330 		needed = false;
331 		break;
332 	}
333 
334 	return needed;
335 }
336 
337 // The general idea is having a resource like a buffer or image that is generated from a given pipeline stage (including host,
338 // transfer and all ray shader stages) and read from another stage, using a barrier to synchronize access to the resource. Read
339 // values are copied to an output host-visible buffer for verification.
340 
341 class BarrierTestCase : public vkt::TestCase
342 {
343 public:
344 							BarrierTestCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& testParams);
~BarrierTestCase(void)345 	virtual					~BarrierTestCase	(void) {}
346 
347 	virtual void			initPrograms		(SourceCollections& programCollection) const;
348 	virtual TestInstance*	createInstance		(Context& context) const;
349 	virtual void			checkSupport		(Context& context) const;
350 
351 private:
352 	TestParams				m_params;
353 };
354 
355 class BarrierTestInstance : public vkt::TestInstance
356 {
357 public:
358 								BarrierTestInstance		(Context& context, const TestParams& testParams);
~BarrierTestInstance(void)359 	virtual						~BarrierTestInstance	(void) {}
360 
361 	virtual tcu::TestStatus		iterate					(void);
362 
363 private:
364 	TestParams					m_params;
365 };
366 
BarrierTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & testParams)367 BarrierTestCase::BarrierTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& testParams)
368 	: vkt::TestCase	(testCtx, name, description)
369 	, m_params		(testParams)
370 {
371 }
372 
initPrograms(SourceCollections & programCollection) const373 void BarrierTestCase::initPrograms (SourceCollections& programCollection) const
374 {
375 	const auto&					wstage					= m_params.writerStage;
376 	const auto&					rstage					= m_params.readerStage;
377 	const bool					readNeedAS				= needsAccelerationStructure(rstage);
378 	const deUint32				readerVerifierBinding	= (readNeedAS ? 2u : 1u); // 0 is the barrier resource, 1 may be the AS.
379 	const ShaderBuildOptions	buildOptions			(programCollection.usedVulkanVersion, SPIRV_VERSION_1_4, 0u, true);
380 	const std::string			valStatement			= "  const uint  val  = id1d + " + de::toString(kValuesOffset) + ";\n";
381 	const std::string			readerSaveStatement		= "  verificationBuffer.data[id1d] = val;\n";
382 
383 	// Common for all ray tracing shaders.
384 	std::stringstream rayTracingIdsStream;
385 	rayTracingIdsStream
386 		<< "  const uint  id1d = gl_LaunchIDEXT.y * " << kImageDim << " + gl_LaunchIDEXT.x;\n"
387 		<< "  const ivec2 id2d = ivec2(gl_LaunchIDEXT.xy);\n"
388 		;
389 	const std::string rayTracingIds = rayTracingIdsStream.str();
390 
391 	// Common for all compute shaders.
392 	std::stringstream computeIdsStream;
393 	computeIdsStream
394 		<< "  const uint  id1d = gl_GlobalInvocationID.y * " << kImageDim << " + gl_GlobalInvocationID.x;\n"
395 		<< "  const ivec2 id2d = ivec2(gl_GlobalInvocationID.xy);\n"
396 		;
397 	const std::string computeIds = computeIdsStream.str();
398 
399 	// Common for all fragment shaders.
400 	std::stringstream fragIdsStream;
401 	fragIdsStream
402 		<< "  const uint  id1d = uint(gl_FragCoord.y) * " << kImageDim << " + uint(gl_FragCoord.x);\n"
403 		<< "  const ivec2 id2d = ivec2(gl_FragCoord.xy);\n"
404 		;
405 	const std::string fragIds = fragIdsStream.str();
406 
407 	// Statements to declare the resource in the writer and reader sides, as well as writing to and reading from it.
408 	std::stringstream writerResourceDecl;
409 	std::stringstream readerResourceDecl;
410 	std::stringstream writeStatement;
411 	std::stringstream readStatement;
412 
413 	switch (m_params.resourceType)
414 	{
415 	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
416 		writerResourceDecl << "layout(set = 0, binding = 0, std140) uniform ubodef { uint data[" << kBufferElements << "]; } ubo;\n";
417 		readerResourceDecl << "layout(set = 0, binding = 0, std140) uniform ubodef { uint data[" << kBufferElements << "]; } ubo;\n";
418 		// No writes can happen from shaders in this case.
419 		readStatement << "  const uint  val  = ubo.data[id1d];\n";
420 		break;
421 	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
422 		writerResourceDecl << "layout(set = 0, binding = 0, std140) buffer ssbodef { uint data[" << kBufferElements << "]; } ssbo;\n";
423 		readerResourceDecl << "layout(set = 0, binding = 0, std140) buffer ssbodef { uint data[" << kBufferElements << "]; } ssbo;\n";
424 		writeStatement << "  ssbo.data[id1d] = val;\n";
425 		readStatement << "  const uint  val  = ssbo.data[id1d];\n";
426 		break;
427 	case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
428 		writerResourceDecl << "layout(r32ui, set = 0, binding = 0) uniform uimage2D simage;\n";
429 		readerResourceDecl << "layout(r32ui, set = 0, binding = 0) uniform uimage2D simage;\n";
430 		writeStatement << "  imageStore(simage, id2d, uvec4(val, 0, 0, 0));\n";
431 		readStatement << "  const uint  val  = imageLoad(simage, id2d).x;\n";
432 		break;
433 	default:
434 		DE_ASSERT(false);
435 		break;
436 	}
437 
438 	// This extra buffer will be used to copy values from the resource as obtained by the reader and will later be verified on the host.
439 	std::stringstream readerVerifierDeclStream;
440 	readerVerifierDeclStream << "layout(set = 0, binding = " << readerVerifierBinding << ") buffer vssbodef { uint data[" << kBufferElements << "]; } verificationBuffer;\n";
441 	const std::string readerVerifierDecl = readerVerifierDeclStream.str();
442 
443 	// These are always used together in writer shaders.
444 	const std::string writerCalcAndWrite = valStatement + writeStatement.str();
445 
446 	// Add shaders that will be used to write to the resource.
447 	if (wstage == Stage::HOST || wstage == Stage::TRANSFER)
448 		; // Nothing to do here.
449 	else if (wstage == Stage::RAYGEN)
450 	{
451 		std::stringstream rgen;
452 		rgen
453 			<< "#version 460 core\n"
454 			<< "#extension GL_EXT_ray_tracing : require\n"
455 			<< writerResourceDecl.str()
456 			<< "void main()\n"
457 			<< "{\n"
458 			<< rayTracingIds
459 			<< writerCalcAndWrite
460 			<< "}\n"
461 			;
462 		programCollection.glslSources.add("writer_rgen") << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
463 	}
464 	else if (wstage == Stage::INTERSECT)
465 	{
466 		programCollection.glslSources.add("writer_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
467 
468 		std::stringstream isect;
469 		isect
470 			<< "#version 460 core\n"
471 			<< "#extension GL_EXT_ray_tracing : require\n"
472 			<< "hitAttributeEXT vec3 hitAttribute;\n"
473 			<< writerResourceDecl.str()
474 			<< "void main()\n"
475 			<< "{\n"
476 			<< rayTracingIds
477 			<< writerCalcAndWrite
478 			<< "  hitAttribute = vec3(0.0f, 0.0f, 0.0f);\n"
479 			<< "  reportIntersectionEXT(1.0f, 0);\n"
480 			<< "}\n"
481 			;
482 		programCollection.glslSources.add("writer_isect") << glu::IntersectionSource(updateRayTracingGLSL(isect.str())) << buildOptions;
483 	}
484 	else if (wstage == Stage::ANY_HIT)
485 	{
486 		programCollection.glslSources.add("writer_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
487 
488 		std::stringstream ahit;
489 		ahit
490 			<< "#version 460 core\n"
491 			<< "#extension GL_EXT_ray_tracing : require\n"
492 			<< "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
493 			<< "hitAttributeEXT vec3 attribs;\n"
494 			<< writerResourceDecl.str()
495 			<< "void main()\n"
496 			<< "{\n"
497 			<< rayTracingIds
498 			<< writerCalcAndWrite
499 			<< "}\n"
500 			;
501 		programCollection.glslSources.add("writer_ahit") << glu::AnyHitSource(updateRayTracingGLSL(ahit.str())) << buildOptions;
502 	}
503 	else if (wstage == Stage::CLOSEST_HIT)
504 	{
505 		programCollection.glslSources.add("writer_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
506 
507 		std::stringstream chit;
508 		chit
509 			<< "#version 460 core\n"
510 			<< "#extension GL_EXT_ray_tracing : require\n"
511 			<< "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
512 			<< "hitAttributeEXT vec3 attribs;\n"
513 			<< writerResourceDecl.str()
514 			<< "void main()\n"
515 			<< "{\n"
516 			<< rayTracingIds
517 			<< writerCalcAndWrite
518 			<< "}\n"
519 			;
520 		programCollection.glslSources.add("writer_chit") << glu::ClosestHitSource(updateRayTracingGLSL(chit.str())) << buildOptions;
521 	}
522 	else if (wstage == Stage::MISS)
523 	{
524 		programCollection.glslSources.add("writer_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
525 
526 		std::stringstream miss;
527 		miss
528 			<< "#version 460 core\n"
529 			<< "#extension GL_EXT_ray_tracing : require\n"
530 			<< "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
531 			<< writerResourceDecl.str()
532 			<< "void main()\n"
533 			<< "{\n"
534 			<< rayTracingIds
535 			<< writerCalcAndWrite
536 			<< "}\n"
537 			;
538 		programCollection.glslSources.add("writer_miss") << glu::MissSource(updateRayTracingGLSL(miss.str())) << buildOptions;
539 	}
540 	else if (wstage == Stage::CALLABLE)
541 	{
542 		{
543 			std::stringstream rgen;
544 			rgen
545 				<< "#version 460 core\n"
546 				<< "#extension GL_EXT_ray_tracing : require\n"
547 				<< "layout(location = 0) callableDataEXT float unusedCallableData;"
548 				<< "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
549 				<< "\n"
550 				<< "void main()\n"
551 				<< "{\n"
552 				<< "  executeCallableEXT(0, 0);\n"
553 				<< "}\n"
554 				;
555 			programCollection.glslSources.add("writer_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
556 		}
557 
558 		std::stringstream callable;
559 		callable
560 			<< "#version 460 core\n"
561 			<< "#extension GL_EXT_ray_tracing : require\n"
562 			<< "layout(location = 0) callableDataInEXT float unusedCallableData;\n"
563 			<< writerResourceDecl.str()
564 			<< "void main()\n"
565 			<< "{\n"
566 			<< rayTracingIds
567 			<< writerCalcAndWrite
568 			<< "}\n"
569 			;
570 		programCollection.glslSources.add("writer_callable") << glu::CallableSource(updateRayTracingGLSL(callable.str())) << buildOptions;
571 	}
572 	else if (wstage == Stage::COMPUTE)
573 	{
574 		std::stringstream compute;
575 		compute
576 			<< "#version 460 core\n"
577 			<< writerResourceDecl.str()
578 			<< "void main()\n"
579 			<< "{\n"
580 			<< computeIds
581 			<< writerCalcAndWrite
582 			<< "}\n"
583 			;
584 		programCollection.glslSources.add("writer_comp") << glu::ComputeSource(compute.str());
585 	}
586 	else if (wstage == Stage::FRAGMENT)
587 	{
588 		{
589 			std::stringstream vert;
590 			vert
591 				<< "#version 460 core\n"
592 				<< "layout(location = 0) in highp vec4 position;\n"
593 				<< "void main()\n"
594 				<< "{\n"
595 				<< "  gl_Position = position;\n"
596 				<< "}\n"
597 				;
598 			programCollection.glslSources.add("writer_aux_vert") << glu::VertexSource(vert.str());
599 		}
600 
601 		std::stringstream frag;
602 		frag
603 			<< "#version 460 core\n"
604 			<< writerResourceDecl.str()
605 			<< "void main()\n"
606 			<< "{\n"
607 			<< fragIds
608 			<< writerCalcAndWrite
609 			<< "}\n"
610 			;
611 		programCollection.glslSources.add("writer_frag") << glu::FragmentSource(frag.str());
612 	}
613 	else
614 	{
615 		DE_ASSERT(false);
616 	}
617 
618 	// These are always used together by reader shaders.
619 	const std::string readerAllDecls	= readerResourceDecl.str() + readerVerifierDecl;
620 	const std::string readerReadAndSave	= readStatement.str() + readerSaveStatement;
621 
622 	// Add shaders that will be used to read from the resource.
623 	if (rstage == Stage::HOST || rstage == Stage::TRANSFER)
624 		; // Nothing to do here.
625 	else if (rstage == Stage::RAYGEN)
626 	{
627 		std::stringstream rgen;
628 		rgen
629 			<< "#version 460 core\n"
630 			<< "#extension GL_EXT_ray_tracing : require\n"
631 			<< readerAllDecls
632 			<< "void main()\n"
633 			<< "{\n"
634 			<< rayTracingIds
635 			<< readerReadAndSave
636 			<< "}\n"
637 			;
638 		programCollection.glslSources.add("reader_rgen") << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
639 	}
640 	else if (rstage == Stage::INTERSECT)
641 	{
642 		programCollection.glslSources.add("reader_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
643 
644 		std::stringstream isect;
645 		isect
646 			<< "#version 460 core\n"
647 			<< "#extension GL_EXT_ray_tracing : require\n"
648 			<< "hitAttributeEXT vec3 hitAttribute;\n"
649 			<< readerAllDecls
650 			<< "void main()\n"
651 			<< "{\n"
652 			<< rayTracingIds
653 			<< readerReadAndSave
654 			<< "  hitAttribute = vec3(0.0f, 0.0f, 0.0f);\n"
655 			<< "  reportIntersectionEXT(1.0f, 0);\n"
656 			<< "}\n"
657 			;
658 		programCollection.glslSources.add("reader_isect") << glu::IntersectionSource(updateRayTracingGLSL(isect.str())) << buildOptions;
659 	}
660 	else if (rstage == Stage::ANY_HIT)
661 	{
662 		programCollection.glslSources.add("reader_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
663 
664 		std::stringstream ahit;
665 		ahit
666 			<< "#version 460 core\n"
667 			<< "#extension GL_EXT_ray_tracing : require\n"
668 			<< "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
669 			<< "hitAttributeEXT vec3 attribs;\n"
670 			<< readerAllDecls
671 			<< "void main()\n"
672 			<< "{\n"
673 			<< rayTracingIds
674 			<< readerReadAndSave
675 			<< "}\n"
676 			;
677 		programCollection.glslSources.add("reader_ahit") << glu::AnyHitSource(updateRayTracingGLSL(ahit.str())) << buildOptions;
678 	}
679 	else if (rstage == Stage::CLOSEST_HIT)
680 	{
681 		programCollection.glslSources.add("reader_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
682 
683 		std::stringstream chit;
684 		chit
685 			<< "#version 460 core\n"
686 			<< "#extension GL_EXT_ray_tracing : require\n"
687 			<< "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
688 			<< "hitAttributeEXT vec3 attribs;\n"
689 			<< readerAllDecls
690 			<< "void main()\n"
691 			<< "{\n"
692 			<< rayTracingIds
693 			<< readerReadAndSave
694 			<< "}\n"
695 			;
696 		programCollection.glslSources.add("reader_chit") << glu::ClosestHitSource(updateRayTracingGLSL(chit.str())) << buildOptions;
697 	}
698 	else if (rstage == Stage::MISS)
699 	{
700 		programCollection.glslSources.add("reader_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
701 
702 		std::stringstream miss;
703 		miss
704 			<< "#version 460 core\n"
705 			<< "#extension GL_EXT_ray_tracing : require\n"
706 			<< "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
707 			<< readerAllDecls
708 			<< "void main()\n"
709 			<< "{\n"
710 			<< rayTracingIds
711 			<< readerReadAndSave
712 			<< "}\n"
713 			;
714 		programCollection.glslSources.add("reader_miss") << glu::MissSource(updateRayTracingGLSL(miss.str())) << buildOptions;
715 	}
716 	else if (rstage == Stage::CALLABLE)
717 	{
718 		{
719 			std::stringstream rgen;
720 			rgen
721 				<< "#version 460 core\n"
722 				<< "#extension GL_EXT_ray_tracing : require\n"
723 				<< "layout(location = 0) callableDataEXT float unusedCallableData;"
724 				<< "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
725 				<< "\n"
726 				<< "void main()\n"
727 				<< "{\n"
728 				<< "  executeCallableEXT(0, 0);\n"
729 				<< "}\n"
730 				;
731 			programCollection.glslSources.add("reader_aux_rgen") << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
732 		}
733 
734 		std::stringstream callable;
735 		callable
736 			<< "#version 460 core\n"
737 			<< "#extension GL_EXT_ray_tracing : require\n"
738 			<< "layout(location = 0) callableDataInEXT float unusedCallableData;\n"
739 			<< readerAllDecls
740 			<< "void main()\n"
741 			<< "{\n"
742 			<< rayTracingIds
743 			<< readerReadAndSave
744 			<< "}\n"
745 			;
746 		programCollection.glslSources.add("reader_callable") << glu::CallableSource(updateRayTracingGLSL(callable.str())) << buildOptions;
747 	}
748 	else if (rstage == Stage::COMPUTE)
749 	{
750 		std::stringstream compute;
751 		compute
752 			<< "#version 460 core\n"
753 			<< readerAllDecls
754 			<< "void main()\n"
755 			<< "{\n"
756 			<< computeIds
757 			<< readerReadAndSave
758 			<< "}\n"
759 			;
760 		programCollection.glslSources.add("reader_comp") << glu::ComputeSource(compute.str());
761 	}
762 	else if (rstage == Stage::FRAGMENT)
763 	{
764 		{
765 			std::stringstream vert;
766 			vert
767 				<< "#version 460 core\n"
768 				<< "layout(location = 0) in highp vec4 position;\n"
769 				<< "void main()\n"
770 				<< "{\n"
771 				<< "  gl_Position = position;\n"
772 				<< "}\n"
773 				;
774 			programCollection.glslSources.add("reader_aux_vert") << glu::VertexSource(vert.str());
775 		}
776 
777 		std::stringstream frag;
778 		frag
779 			<< "#version 460 core\n"
780 			<< readerAllDecls
781 			<< "void main()\n"
782 			<< "{\n"
783 			<< fragIds
784 			<< readerReadAndSave
785 			<< "}\n"
786 			;
787 		programCollection.glslSources.add("reader_frag") << glu::FragmentSource(frag.str());
788 	}
789 	else
790 	{
791 		DE_ASSERT(false);
792 	}
793 }
794 
createInstance(Context & context) const795 TestInstance* BarrierTestCase::createInstance (Context& context) const
796 {
797 	return new BarrierTestInstance(context, m_params);
798 }
799 
checkSupport(Context & context) const800 void BarrierTestCase::checkSupport (Context& context) const
801 {
802 	if (m_params.writerStage == Stage::FRAGMENT)
803 	{
804 		const auto& features = context.getDeviceFeatures();
805 
806 		if (!features.fragmentStoresAndAtomics)
807 			TCU_THROW(NotSupportedError, "Fragment shader does not support stores");
808 	}
809 
810 	if (isRayTracingStage(m_params.readerStage) || isRayTracingStage(m_params.writerStage))
811 	{
812 		context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
813 		context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
814 
815 		const auto& rtFeatures = context.getRayTracingPipelineFeatures();
816 		if (!rtFeatures.rayTracingPipeline)
817 			TCU_THROW(NotSupportedError, "Ray Tracing pipelines not supported");
818 
819 		const auto& asFeatures = context.getAccelerationStructureFeatures();
820 		if (!asFeatures.accelerationStructure)
821 			TCU_FAIL("VK_KHR_acceleration_structure supported without accelerationStructure support");
822 	}
823 }
824 
BarrierTestInstance(Context & context,const TestParams & testParams)825 BarrierTestInstance::BarrierTestInstance (Context& context, const TestParams& testParams)
826 	: vkt::TestInstance	(context)
827 	, m_params			(testParams)
828 {
829 }
830 
831 // Creates a buffer with kBufferElements elements of type deUint32 and std140 padding.
makeStd140Buffer(const DeviceInterface & vkd,VkDevice device,Allocator & alloc,VkBufferUsageFlags flags,MemoryRequirement memReq)832 std::unique_ptr<BufferWithMemory> makeStd140Buffer (const DeviceInterface& vkd, VkDevice device, Allocator& alloc, VkBufferUsageFlags flags, MemoryRequirement memReq)
833 {
834 	std::unique_ptr<BufferWithMemory> buffer;
835 
836 	const auto bufferCreateInfo = makeBufferCreateInfo(static_cast<VkDeviceSize>(kBufferSize), flags);
837 	buffer.reset(new BufferWithMemory(vkd, device, alloc, bufferCreateInfo, memReq));
838 
839 	return buffer;
840 }
841 
842 // Fill buffer with data using std140 padding rules.
fillStd140Buffer(const DeviceInterface & vkd,VkDevice device,const BufferWithMemory & buffer)843 void fillStd140Buffer (const DeviceInterface& vkd, VkDevice device, const BufferWithMemory& buffer)
844 {
845 	// Buffer host ptr.
846 	auto& bufferAlloc	= buffer.getAllocation();
847 	auto* bufferPtr		= bufferAlloc.getHostPtr();
848 
849 	// Fill buffer with data. This uses the same strategy as the writer shaders.
850 	std::vector<tcu::UVec4> bufferData(kBufferElements, tcu::UVec4(kValuesOffset, 0u, 0u, 0u));
851 	for (size_t i = 0; i < bufferData.size(); ++i)
852 		bufferData[i].x() += static_cast<deUint32>(i);
853 	deMemcpy(bufferPtr, bufferData.data(), static_cast<size_t>(kBufferSize));
854 	flushAlloc(vkd, device, bufferAlloc);
855 }
856 
857 // Fill buffer with data using std430 padding rules (compact integers).
fillStd430Buffer(const DeviceInterface & vkd,VkDevice device,const BufferWithMemory & buffer)858 void fillStd430Buffer (const DeviceInterface& vkd, VkDevice device, const BufferWithMemory& buffer)
859 {
860 	// Buffer host ptr.
861 	auto& bufferAlloc	= buffer.getAllocation();
862 	auto* bufferPtr		= bufferAlloc.getHostPtr();
863 
864 	// Fill buffer with data. This uses the same strategy as the writer shaders.
865 	std::vector<deUint32> bufferData(kBufferElements);
866 	std::iota(begin(bufferData), end(bufferData), kValuesOffset);
867 	deMemcpy(bufferPtr, bufferData.data(), static_cast<size_t>(kBufferSize430));
868 	flushAlloc(vkd, device, bufferAlloc);
869 }
870 
871 // Creates a host-visible std430 buffer with kBufferElements elements of type deUint32. If requested, fill buffer with values
872 // starting at kValuesOffset.
makeStd430BufferImpl(const DeviceInterface & vkd,VkDevice device,Allocator & alloc,VkBufferUsageFlags flags,bool fill)873 std::unique_ptr<BufferWithMemory> makeStd430BufferImpl (const DeviceInterface& vkd, VkDevice device, Allocator& alloc, VkBufferUsageFlags flags, bool fill)
874 {
875 	std::unique_ptr<BufferWithMemory> buffer;
876 
877 	const auto bufferCreateInfo = makeBufferCreateInfo(static_cast<VkDeviceSize>(kBufferSize430), flags);
878 	buffer.reset(new BufferWithMemory(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible));
879 
880 	if (fill)
881 		fillStd430Buffer(vkd, device, *buffer);
882 
883 	return buffer;
884 }
885 
makeStd430Buffer(const DeviceInterface & vkd,VkDevice device,Allocator & alloc,VkBufferUsageFlags flags)886 std::unique_ptr<BufferWithMemory> makeStd430Buffer (const DeviceInterface& vkd, VkDevice device, Allocator& alloc, VkBufferUsageFlags flags)
887 {
888 	return makeStd430BufferImpl(vkd, device, alloc, flags, false);
889 }
890 
makeStd430BufferFilled(const DeviceInterface & vkd,VkDevice device,Allocator & alloc,VkBufferUsageFlags flags)891 std::unique_ptr<BufferWithMemory> makeStd430BufferFilled (const DeviceInterface& vkd, VkDevice device, Allocator& alloc, VkBufferUsageFlags flags)
892 {
893 	return makeStd430BufferImpl(vkd, device, alloc, flags, true);
894 }
895 
896 // Helper struct to group data related to the writer or reader stages.
897 // Not every member will be used at the same time.
898 struct StageData
899 {
900 	Move<VkDescriptorSetLayout>						descriptorSetLayout;
901 	Move<VkPipelineLayout>							pipelineLayout;
902 
903 	Move<VkDescriptorPool>							descriptorPool;
904 	Move<VkDescriptorSet>							descriptorSet;
905 
906 	Move<VkPipeline>								pipeline;
907 	Move<VkRenderPass>								renderPass;
908 	Move<VkFramebuffer>								framebuffer;
909 	std::unique_ptr<BufferWithMemory>				vertexBuffer;
910 
911 	de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure;
912 	de::MovePtr<TopLevelAccelerationStructure>		topLevelAccelerationStructure;
913 
914 	de::MovePtr<BufferWithMemory>					raygenShaderBindingTable;
915 	de::MovePtr<BufferWithMemory>					missShaderBindingTable;
916 	de::MovePtr<BufferWithMemory>					hitShaderBindingTable;
917 	de::MovePtr<BufferWithMemory>					callableShaderBindingTable;
918 
919 	VkStridedDeviceAddressRegionKHR					raygenShaderBindingTableRegion;
920 	VkStridedDeviceAddressRegionKHR					missShaderBindingTableRegion;
921 	VkStridedDeviceAddressRegionKHR					hitShaderBindingTableRegion;
922 	VkStridedDeviceAddressRegionKHR					callableShaderBindingTableRegion;
923 
StageDatavkt::RayTracing::__anon2c1cb5820111::StageData924 	StageData ()
925 		: descriptorSetLayout				()
926 		, pipelineLayout					()
927 		, descriptorPool					()
928 		, descriptorSet						()
929 		, pipeline							()
930 		, renderPass						()
931 		, framebuffer						()
932 		, vertexBuffer						()
933 		, bottomLevelAccelerationStructure	()
934 		, topLevelAccelerationStructure		()
935 		, raygenShaderBindingTable			()
936 		, missShaderBindingTable			()
937 		, hitShaderBindingTable				()
938 		, callableShaderBindingTable		()
939 		, raygenShaderBindingTableRegion	(makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0))
940 		, missShaderBindingTableRegion		(makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0))
941 		, hitShaderBindingTableRegion		(makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0))
942 		, callableShaderBindingTableRegion	(makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0))
943 	{
944 	}
945 
946 	// Make sure we don't mistakenly pass one of these by value.
947 	StageData (const StageData&)	= delete;
948 	StageData (StageData&&)			= delete;
949 };
950 
951 // Auxiliar function to update the descriptor set for the writer or reader stages.
updateDescriptorSet(const DeviceInterface & vkd,VkDevice device,VkCommandBuffer cmdBuffer,Allocator & alloc,VkDescriptorType resourceType,Stage stage,StageData & stageData,BufferWithMemory * resourceBuffer,VkImageView resourceImgView,VkImageLayout layout,bool asNeeded,BufferWithMemory * verificationBuffer)952 void updateDescriptorSet (const DeviceInterface& vkd, VkDevice device, VkCommandBuffer cmdBuffer, Allocator& alloc, VkDescriptorType resourceType, Stage stage, StageData& stageData, BufferWithMemory* resourceBuffer, VkImageView resourceImgView, VkImageLayout layout, bool asNeeded, BufferWithMemory* verificationBuffer)
953 {
954 	DescriptorSetUpdateBuilder						updateBuilder;
955 	VkWriteDescriptorSetAccelerationStructureKHR	writeASInfo;
956 
957 	if (resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || resourceType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
958 	{
959 		const auto descriptorBufferInfo = makeDescriptorBufferInfo(resourceBuffer->get(), 0ull, VK_WHOLE_SIZE);
960 		updateBuilder.writeSingle(stageData.descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), resourceType, &descriptorBufferInfo);
961 	}
962 	else if (resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
963 	{
964 		const auto descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, resourceImgView, layout);
965 		updateBuilder.writeSingle(stageData.descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), resourceType, &descriptorImageInfo);
966 	}
967 	else
968 	{
969 		DE_ASSERT(false);
970 	}
971 
972 	// Create top and bottom level acceleration structures if needed.
973 	if (asNeeded)
974 	{
975 		stageData.bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
976 		stageData.bottomLevelAccelerationStructure->setDefaultGeometryData(getShaderStageFlagBits(stage));
977 		stageData.bottomLevelAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, alloc);
978 
979 		stageData.topLevelAccelerationStructure = makeTopLevelAccelerationStructure();
980 		stageData.topLevelAccelerationStructure->setInstanceCount(1);
981 		stageData.topLevelAccelerationStructure->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(stageData.bottomLevelAccelerationStructure.release()));
982 		stageData.topLevelAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, alloc);
983 
984 		writeASInfo.sType						= VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
985 		writeASInfo.pNext						= nullptr;
986 		writeASInfo.accelerationStructureCount	= 1u;
987 		writeASInfo.pAccelerationStructures		= stageData.topLevelAccelerationStructure.get()->getPtr();
988 
989 		updateBuilder.writeSingle(stageData.descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &writeASInfo);
990 	}
991 
992 	if (verificationBuffer)
993 	{
994 		const deUint32	bindingNumber			= (asNeeded ? 2u : 1u);
995 		const auto		descriptorBufferInfo	= makeDescriptorBufferInfo(verificationBuffer->get(), 0ull, VK_WHOLE_SIZE);
996 
997 		updateBuilder.writeSingle(stageData.descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(bindingNumber), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo);
998 	}
999 
1000 	updateBuilder.update(vkd, device);
1001 }
1002 
1003 // Auxiliar function to create the writer or reader compute pipeline
createComputePipeline(const DeviceInterface & vkd,VkDevice device,Context & context,const char * shaderName,StageData & stageData)1004 void createComputePipeline (const DeviceInterface& vkd, VkDevice device, Context& context, const char* shaderName, StageData& stageData)
1005 {
1006 	const auto shaderModule = createShaderModule(vkd, device, context.getBinaryCollection().get(shaderName), 0u);
1007 
1008 	const VkPipelineShaderStageCreateInfo stageInfo =
1009 	{
1010 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType						sType;
1011 		nullptr,												//	const void*							pNext;
1012 		0u,														//	VkPipelineShaderStageCreateFlags	flags;
1013 		VK_SHADER_STAGE_COMPUTE_BIT,							//	VkShaderStageFlagBits				stage;
1014 		shaderModule.get(),										//	VkShaderModule						module;
1015 		"main",													//	const char*							pName;
1016 		nullptr,												//	const VkSpecializationInfo*			pSpecializationInfo;
1017 	};
1018 
1019 	const VkComputePipelineCreateInfo createInfo =
1020 	{
1021 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,	//	VkStructureType					sType;
1022 		nullptr,										//	const void*						pNext;
1023 		0u,												//	VkPipelineCreateFlags			flags;
1024 		stageInfo,										//	VkPipelineShaderStageCreateInfo	stage;
1025 		stageData.pipelineLayout.get(),					//	VkPipelineLayout				layout;
1026 		DE_NULL,										//	VkPipeline						basePipelineHandle;
1027 		0,												//	deInt32							basePipelineIndex;
1028 	};
1029 
1030 	// Compute pipeline.
1031 	stageData.pipeline = createComputePipeline(vkd, device, DE_NULL, &createInfo);
1032 }
1033 
1034 // Auxiliar function to record commands using the compute pipeline.
useComputePipeline(const DeviceInterface & vkd,VkCommandBuffer cmdBuffer,StageData & stageData)1035 void useComputePipeline (const DeviceInterface& vkd, VkCommandBuffer cmdBuffer, StageData& stageData)
1036 {
1037 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, stageData.pipeline.get());
1038 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, stageData.pipelineLayout.get(), 0u, 1u, &stageData.descriptorSet.get(), 0u, nullptr);
1039 	vkd.cmdDispatch(cmdBuffer, kImageDim, kImageDim, 1u);
1040 }
1041 
1042 // Auxiliar function to create graphics pipeline objects for writer or reader stages.
createGraphicsPipelineObjects(const DeviceInterface & vkd,VkDevice device,Allocator & alloc,Context & context,const char * vertShaderName,const char * fragShaderName,StageData & stageData)1043 void createGraphicsPipelineObjects (const DeviceInterface& vkd, VkDevice device, Allocator& alloc, Context& context, const char* vertShaderName, const char* fragShaderName, StageData& stageData)
1044 {
1045 	const auto vertShader = createShaderModule(vkd, device, context.getBinaryCollection().get(vertShaderName), 0u);
1046 	const auto fragShader = createShaderModule(vkd, device, context.getBinaryCollection().get(fragShaderName), 0u);
1047 
1048 	// Render pass.
1049 	const auto subpassDescription = makeSubpassDescription(0u, VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, nullptr, 0u, nullptr, nullptr, nullptr, 0u, nullptr);
1050 	const VkRenderPassCreateInfo renderPassInfo =
1051 	{
1052 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	//	VkStructureType					sType;
1053 		nullptr,									//	const void*						pNext;
1054 		0u,											//	VkRenderPassCreateFlags			flags;
1055 		0u,											//	deUint32						attachmentCount;
1056 		nullptr,									//	const VkAttachmentDescription*	pAttachments;
1057 		1u,											//	deUint32						subpassCount;
1058 		&subpassDescription,						//	const VkSubpassDescription*		pSubpasses;
1059 		0u,											//	deUint32						dependencyCount;
1060 		nullptr,									//	const VkSubpassDependency*		pDependencies;
1061 	};
1062 	stageData.renderPass = createRenderPass(vkd, device, &renderPassInfo);
1063 
1064 	// Viewport.
1065 	const auto viewport = makeViewport(kImageExtent);
1066 	const std::vector<VkViewport> viewports(1u, viewport);
1067 
1068 	// Scissor.
1069 	const auto scissor = makeRect2D(kImageExtent);
1070 	const std::vector<VkRect2D> scissors(1u, scissor);
1071 
1072 	// Pipeline.
1073 	stageData.pipeline = makeGraphicsPipeline(vkd, device, stageData.pipelineLayout.get(), vertShader.get(), DE_NULL, DE_NULL, DE_NULL, fragShader.get(), stageData.renderPass.get(), viewports, scissors);
1074 
1075 	// Framebuffer.
1076 	stageData.framebuffer = makeFramebuffer(vkd, device, stageData.renderPass.get(), 0u, nullptr, kImageDim, kImageDim);
1077 
1078 	// Vertex buffer with full-screen quad.
1079 	const auto			vertexBufferSize	= static_cast<VkDeviceSize>(kFullScreenQuad.size() * sizeof(decltype(kFullScreenQuad)::value_type));
1080 	const auto			vertexBufferInfo	= makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1081 
1082 	stageData.vertexBuffer.reset(new BufferWithMemory(vkd, device, alloc, vertexBufferInfo, MemoryRequirement::HostVisible));
1083 	const auto&			vertexBufferAlloc	= stageData.vertexBuffer->getAllocation();
1084 
1085 	deMemcpy(vertexBufferAlloc.getHostPtr(), kFullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
1086 	flushAlloc(vkd, device, vertexBufferAlloc);
1087 }
1088 
1089 // Auxiliar function to record commands using the graphics pipeline.
useGraphicsPipeline(const DeviceInterface & vkd,VkCommandBuffer cmdBuffer,StageData & stageData)1090 void useGraphicsPipeline (const DeviceInterface& vkd, VkCommandBuffer cmdBuffer, StageData& stageData)
1091 {
1092 	const VkDeviceSize	vertexBufferOffset	= 0ull;
1093 	const auto			scissor				= makeRect2D(kImageExtent);
1094 
1095 	beginRenderPass(vkd, cmdBuffer, stageData.renderPass.get(), stageData.framebuffer.get(), scissor);
1096 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, stageData.pipeline.get());
1097 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, stageData.pipelineLayout.get(), 0u, 1u, &stageData.descriptorSet.get(), 0u, nullptr);
1098 	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &stageData.vertexBuffer->get(), &vertexBufferOffset);
1099 	vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(kFullScreenQuad.size()), 1u, 0u, 0u);
1100 	endRenderPass(vkd, cmdBuffer);
1101 }
1102 
1103 // Auxiliar function to create ray tracing pipelines for the writer or reader stages.
createRayTracingPipelineData(const DeviceInterface & vkd,VkDevice device,Allocator & alloc,Context & context,Stage stage,StageData & stageData,deUint32 shaderGroupHandleSize,deUint32 shaderGroupBaseAlignment,const char * rgenAuxName,const char * rgenName,const char * isectName,const char * ahitName,const char * chitName,const char * missName,const char * callableName)1104 void createRayTracingPipelineData (const DeviceInterface& vkd, VkDevice device, Allocator& alloc, Context& context,
1105 								   Stage stage, StageData& stageData, deUint32 shaderGroupHandleSize, deUint32 shaderGroupBaseAlignment,
1106 								   const char* rgenAuxName, const char* rgenName, const char* isectName, const char* ahitName, const char* chitName, const char* missName, const char* callableName)
1107 {
1108 	// Ray tracing stage
1109 	DE_ASSERT(isRayTracingStage(stage));
1110 
1111 	if (stage == Stage::RAYGEN)
1112 	{
1113 		const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1114 
1115 		rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(rgenName), 0), 0);
1116 
1117 		stageData.pipeline = rayTracingPipeline->createPipeline(vkd, device, stageData.pipelineLayout.get());
1118 
1119 		stageData.raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1120 		stageData.raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1121 	}
1122 	else if (stage == Stage::INTERSECT)
1123 	{
1124 		const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1125 
1126 		rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get(rgenAuxName), 0), 0);
1127 		rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get(isectName), 0), 1);
1128 
1129 		stageData.pipeline = rayTracingPipeline->createPipeline(vkd, device, stageData.pipelineLayout.get());
1130 
1131 		stageData.raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1132 		stageData.raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1133 
1134 		stageData.hitShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1135 		stageData.hitShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1136 	}
1137 	else if (stage == Stage::ANY_HIT)
1138 	{
1139 		const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1140 
1141 		rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get(rgenAuxName), 0), 0);
1142 		rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get(ahitName), 0), 1);
1143 
1144 		stageData.pipeline = rayTracingPipeline->createPipeline(vkd, device, stageData.pipelineLayout.get());
1145 
1146 		stageData.raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1147 		stageData.raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1148 
1149 		stageData.hitShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1150 		stageData.hitShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1151 	}
1152 	else if (stage == Stage::CLOSEST_HIT)
1153 	{
1154 		const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1155 
1156 		rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get(rgenAuxName), 0), 0);
1157 		rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get(chitName), 0), 1);
1158 
1159 		stageData.pipeline = rayTracingPipeline->createPipeline(vkd, device, stageData.pipelineLayout.get());
1160 
1161 		stageData.raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1162 		stageData.raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1163 
1164 		stageData.hitShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1165 		stageData.hitShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1166 	}
1167 	else if (stage == Stage::MISS)
1168 	{
1169 		const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1170 
1171 		rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get(rgenAuxName), 0), 0);
1172 		rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get(missName), 0), 1);
1173 
1174 		stageData.pipeline = rayTracingPipeline->createPipeline(vkd, device, stageData.pipelineLayout.get());
1175 
1176 		stageData.raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1177 		stageData.raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1178 
1179 		stageData.missShaderBindingTable		= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1180 		stageData.missShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1181 	}
1182 	else if (stage == Stage::CALLABLE)
1183 	{
1184 		const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1185 
1186 		rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get(rgenAuxName), 0), 0);
1187 		rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get(callableName), 0), 1);
1188 
1189 		stageData.pipeline = rayTracingPipeline->createPipeline(vkd, device, stageData.pipelineLayout.get());
1190 
1191 		stageData.raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1192 		stageData.raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1193 
1194 		stageData.callableShaderBindingTable		= rayTracingPipeline->createShaderBindingTable(vkd, device, stageData.pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1195 		stageData.callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, stageData.callableShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1196 	}
1197 	else
1198 	{
1199 		DE_ASSERT(false);
1200 	}
1201 }
1202 
1203 // Auxiliar function to record commands using the ray tracing pipeline for the writer or reader stages.
useRayTracingPipeline(const DeviceInterface & vkd,VkCommandBuffer cmdBuffer,StageData & stageData)1204 void useRayTracingPipeline (const DeviceInterface& vkd, VkCommandBuffer cmdBuffer, StageData& stageData)
1205 {
1206 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, stageData.pipeline.get());
1207 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, stageData.pipelineLayout.get(), 0u, 1u, &stageData.descriptorSet.get(), 0u, nullptr);
1208 	vkd.cmdTraceRaysKHR(cmdBuffer, &stageData.raygenShaderBindingTableRegion, &stageData.missShaderBindingTableRegion, &stageData.hitShaderBindingTableRegion, &stageData.callableShaderBindingTableRegion, kImageDim, kImageDim, 1u);
1209 }
1210 
iterate(void)1211 tcu::TestStatus BarrierTestInstance::iterate (void)
1212 {
1213 	const auto& vki						= m_context.getInstanceInterface();
1214 	const auto	physicalDevice			= m_context.getPhysicalDevice();
1215 	const auto&	vkd						= m_context.getDeviceInterface();
1216 	const auto	device					= m_context.getDevice();
1217 	const auto	queue					= m_context.getUniversalQueue();
1218 	const auto	familyIndex				= m_context.getUniversalQueueFamilyIndex();
1219 	auto&		alloc					= m_context.getDefaultAllocator();
1220 	const auto	imageSubresourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1221 	const bool	rtInUse					= (isRayTracingStage(m_params.readerStage) || isRayTracingStage(m_params.writerStage));
1222 
1223 	// Stage data for the writer and reader stages.
1224 	StageData writerStageData;
1225 	StageData readerStageData;
1226 
1227 	// Get some ray tracing properties.
1228 	deUint32 shaderGroupHandleSize		= 0u;
1229 	deUint32 shaderGroupBaseAlignment	= 1u;
1230 	if (rtInUse)
1231 	{
1232 		const auto rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
1233 		shaderGroupHandleSize				= rayTracingPropertiesKHR->getShaderGroupHandleSize();
1234 		shaderGroupBaseAlignment			= rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
1235 	}
1236 
1237 	// Shader stages involved.
1238 	const auto writerStages		= getStageFlags(m_params.writerStage);
1239 	const auto readerStages		= getStageFlags(m_params.readerStage);
1240 	const auto allStages		= (writerStages | readerStages);
1241 	const bool writerNeedsAS	= needsAccelerationStructure(m_params.writerStage);
1242 	const bool readerNeedsAS	= needsAccelerationStructure(m_params.readerStage);
1243 
1244 	// Command buffer.
1245 	const auto cmdPool		= makeCommandPool(vkd, device, familyIndex);
1246 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1247 	const auto cmdBuffer	= cmdBufferPtr.get();
1248 
1249 	beginCommandBuffer(vkd, cmdBuffer);
1250 
1251 	std::unique_ptr<ImageWithMemory>	resourceImg;
1252 	Move<VkImageView>					resourceImgView;
1253 	VkImageLayout						resourceImgLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
1254 	const auto							resourceImgSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1255 	std::unique_ptr<BufferWithMemory>	stagingBuffer;
1256 	std::unique_ptr<BufferWithMemory>	resourceBuffer;
1257 	std::unique_ptr<BufferWithMemory>	verificationBuffer;
1258 	const VkBufferUsageFlags			stagingBufferFlags			= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1259 
1260 	// Create verification buffer for later use.
1261 	{
1262 		VkBufferUsageFlags verificationBufferFlags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1263 		if (m_params.readerStage == Stage::TRANSFER)
1264 			verificationBufferFlags |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1265 
1266 		verificationBuffer = makeStd430Buffer(vkd, device, alloc, verificationBufferFlags);
1267 	}
1268 
1269 	// Create resource buffer or resource image.
1270 	if (m_params.resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1271 	{
1272 		if (m_params.resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
1273 			DE_ASSERT(m_params.writerStage == Stage::HOST || m_params.writerStage == Stage::TRANSFER);
1274 
1275 		VkBufferUsageFlags bufferFlags	= ((m_params.resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
1276 										? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
1277 										: VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1278 
1279 		if (m_params.writerStage == Stage::TRANSFER)
1280 			bufferFlags |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1281 
1282 		if (m_params.readerStage == Stage::TRANSFER)
1283 			bufferFlags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1284 
1285 		MemoryRequirement bufferMemReq = (resourceNeedsHostVisibleMemory(m_params) ? MemoryRequirement::HostVisible : MemoryRequirement::Any);
1286 		resourceBuffer = makeStd140Buffer(vkd, device, alloc, bufferFlags, bufferMemReq);
1287 	}
1288 	else if (m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1289 	{
1290 		DE_ASSERT(m_params.writerStage != Stage::HOST);
1291 
1292 		VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_STORAGE_BIT;
1293 
1294 		if (m_params.writerStage == Stage::TRANSFER)
1295 			imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1296 
1297 		if (m_params.readerStage == Stage::TRANSFER)
1298 			imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1299 
1300 		const VkImageCreateInfo resourceImageInfo =
1301 		{
1302 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
1303 			nullptr,								//	const void*				pNext;
1304 			0u,										//	VkImageCreateFlags		flags;
1305 			VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
1306 			kImageFormat,							//	VkFormat				format;
1307 			kImageExtent,							//	VkExtent3D				extent;
1308 			1u,										//	deUint32				mipLevels;
1309 			1u,										//	deUint32				arrayLayers;
1310 			VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
1311 			VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
1312 			imageUsage,								//	VkImageUsageFlags		usage;
1313 			VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
1314 			0u,										//	deUint32				queueFamilyIndexCount;
1315 			nullptr,								//	const deUint32*			pQueueFamilyIndices;
1316 			VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
1317 		};
1318 		resourceImg.reset(new ImageWithMemory(vkd, device, alloc, resourceImageInfo, MemoryRequirement::Any));
1319 		resourceImgLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1320 
1321 		// Image view.
1322 		resourceImgView = makeImageView(vkd, device, resourceImg->get(), VK_IMAGE_VIEW_TYPE_2D, kImageFormat, resourceImgSubresourceRange);
1323 	}
1324 	else
1325 	{
1326 		DE_ASSERT(false);
1327 	}
1328 
1329 	// Populate resource from the writer stage.
1330 	if (m_params.writerStage == Stage::HOST)
1331 	{
1332 		DE_ASSERT(m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || m_params.resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
1333 
1334 		// Fill buffer data from the host.
1335 		fillStd140Buffer(vkd, device, *resourceBuffer);
1336 	}
1337 	else if (m_params.writerStage == Stage::TRANSFER)
1338 	{
1339 		// Similar to the previous one, but using a staging buffer.
1340 		if (m_params.resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1341 		{
1342 			// Create and fill staging buffer.
1343 			stagingBuffer = makeStd140Buffer(vkd, device, alloc, stagingBufferFlags, MemoryRequirement::HostVisible);
1344 			fillStd140Buffer(vkd, device, *stagingBuffer);
1345 
1346 			// Fill resource buffer using a transfer operation.
1347 			const auto region	= makeBufferCopy(0u, 0u, static_cast<VkDeviceSize>(kBufferSize));
1348 			const auto barrier	= makeMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1349 			vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1u, &barrier, 0u, nullptr, 0u, nullptr);
1350 			vkd.cmdCopyBuffer(cmdBuffer, stagingBuffer->get(), resourceBuffer->get(), 1u, &region);
1351 		}
1352 		else if (m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1353 		{
1354 			// Prepare staging buffer with packed pixels.
1355 			stagingBuffer = makeStd430BufferFilled(vkd, device, alloc, stagingBufferFlags);
1356 
1357 			// Barrier for the staging buffer.
1358 			const auto stagingBufferBarrier = makeMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1359 			vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1u, &stagingBufferBarrier, 0u, nullptr, 0u, nullptr);
1360 
1361 			// Transition image to the proper layout.
1362 			const auto expectedLayout = ((m_params.barrierType == BarrierType::SPECIFIC) ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL);
1363 			if (expectedLayout != resourceImgLayout)
1364 			{
1365 				const auto imgBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, resourceImgLayout, expectedLayout, resourceImg->get(), resourceImgSubresourceRange);
1366 				vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &imgBarrier);
1367 				resourceImgLayout = expectedLayout;
1368 			}
1369 
1370 			// Copy buffer to image.
1371 			const auto bufferImageCopy = makeBufferImageCopy(kImageExtent, imageSubresourceLayers);
1372 			vkd.cmdCopyBufferToImage(cmdBuffer, stagingBuffer->get(), resourceImg->get(), resourceImgLayout, 1u, &bufferImageCopy);
1373 		}
1374 		else
1375 		{
1376 			DE_ASSERT(false);
1377 		}
1378 	}
1379 	else
1380 	{
1381 		// Other cases use pipelines and a shader to fill the resource.
1382 
1383 		// Descriptor set layout.
1384 		DescriptorSetLayoutBuilder dslBuilder;
1385 		dslBuilder.addBinding(m_params.resourceType, 1u, allStages, nullptr);	// The resource is used in the writer and reader stages.
1386 		if (writerNeedsAS)
1387 			dslBuilder.addBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1u, writerStages, nullptr);
1388 		writerStageData.descriptorSetLayout = dslBuilder.build(vkd, device);
1389 
1390 		// Pipeline layout.
1391 		writerStageData.pipelineLayout = makePipelineLayout(vkd, device, writerStageData.descriptorSetLayout.get());
1392 
1393 		// Descriptor pool and set.
1394 		DescriptorPoolBuilder poolBuilder;
1395 		poolBuilder.addType(m_params.resourceType);
1396 		if (writerNeedsAS)
1397 			poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
1398 		writerStageData.descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1399 		writerStageData.descriptorSet = makeDescriptorSet(vkd, device, writerStageData.descriptorPool.get(), writerStageData.descriptorSetLayout.get());
1400 
1401 		// Update descriptor set.
1402 		updateDescriptorSet(vkd, device, cmdBuffer, alloc, m_params.resourceType, m_params.writerStage, writerStageData, resourceBuffer.get(), resourceImgView.get(), VK_IMAGE_LAYOUT_GENERAL, writerNeedsAS, nullptr);
1403 
1404 		if (m_params.writerStage == Stage::COMPUTE)
1405 		{
1406 			createComputePipeline(vkd, device, m_context, "writer_comp", writerStageData);
1407 
1408 			if (m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1409 			{
1410 				// Make sure the image is in the proper layout for shader writes.
1411 				const auto expectedLayout = VK_IMAGE_LAYOUT_GENERAL;
1412 				if (expectedLayout != resourceImgLayout)
1413 				{
1414 					const auto imgBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, resourceImgLayout, expectedLayout, resourceImg->get(), resourceImgSubresourceRange);
1415 					vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &imgBarrier);
1416 					resourceImgLayout = expectedLayout;
1417 				}
1418 			}
1419 
1420 			// Generate the resource using the pipeline.
1421 			useComputePipeline(vkd, cmdBuffer, writerStageData);
1422 		}
1423 		else if (m_params.writerStage == Stage::FRAGMENT)
1424 		{
1425 			createGraphicsPipelineObjects(vkd, device, alloc, m_context, "writer_aux_vert", "writer_frag", writerStageData);
1426 
1427 			if (m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1428 			{
1429 				// Make sure the image is in the proper layout for shader writes.
1430 				const auto expectedLayout = VK_IMAGE_LAYOUT_GENERAL;
1431 				if (expectedLayout != resourceImgLayout)
1432 				{
1433 					const auto imgBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, resourceImgLayout, expectedLayout, resourceImg->get(), resourceImgSubresourceRange);
1434 					vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &imgBarrier);
1435 					resourceImgLayout = expectedLayout;
1436 				}
1437 			}
1438 
1439 			useGraphicsPipeline(vkd, cmdBuffer, writerStageData);
1440 		}
1441 		else
1442 		{
1443 			createRayTracingPipelineData(vkd, device, alloc, m_context, m_params.writerStage, writerStageData, shaderGroupHandleSize, shaderGroupBaseAlignment,
1444 										 "writer_aux_rgen", "writer_rgen", "writer_isect", "writer_ahit", "writer_chit", "writer_miss", "writer_callable");
1445 
1446 			if (m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1447 			{
1448 				// Make sure the image is in the proper layout for shader writes.
1449 				const auto expectedLayout = VK_IMAGE_LAYOUT_GENERAL;
1450 				if (expectedLayout != resourceImgLayout)
1451 				{
1452 					const auto imgBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, resourceImgLayout, expectedLayout, resourceImg->get(), resourceImgSubresourceRange);
1453 					vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, 0u, 0u, nullptr, 0u, nullptr, 1u, &imgBarrier);
1454 					resourceImgLayout = expectedLayout;
1455 				}
1456 			}
1457 
1458 			useRayTracingPipeline(vkd, cmdBuffer, writerStageData);
1459 		}
1460 	}
1461 
1462 	// Main barrier to synchronize the writer stage to the reader stage.
1463 	const auto writerPipelineStage	= getPipelineStage(m_params.writerStage);
1464 	const auto readerPipelineStage	= getPipelineStage(m_params.readerStage);
1465 	const auto writerAccessFlag		= getWriterAccessFlag(m_params.writerStage);
1466 	const auto readerAccessFlag		= getReaderAccessFlag(m_params.readerStage, m_params.resourceType);
1467 
1468 	if (m_params.barrierType == BarrierType::GENERAL)
1469 	{
1470 		const auto memoryBarrier = makeMemoryBarrier(writerAccessFlag, readerAccessFlag);
1471 		vkd.cmdPipelineBarrier(cmdBuffer, writerPipelineStage, readerPipelineStage, 0u, 1u, &memoryBarrier, 0u, nullptr, 0u, nullptr);
1472 		// Note the image will remain in the general layout in this case.
1473 		if (m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1474 			DE_ASSERT(resourceImgLayout == VK_IMAGE_LAYOUT_GENERAL);
1475 	}
1476 	else if (m_params.barrierType == BarrierType::SPECIFIC)
1477 	{
1478 		if (m_params.resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1479 		{
1480 			const auto bufferBarrier = makeBufferMemoryBarrier(writerAccessFlag, readerAccessFlag, resourceBuffer->get(), 0ull, VK_WHOLE_SIZE);
1481 			vkd.cmdPipelineBarrier(cmdBuffer, writerPipelineStage, readerPipelineStage, 0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
1482 		}
1483 		else if (m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1484 		{
1485 			// We'll switch the image layout from the current layout to the one the reader expects.
1486 			const auto newLayout	= getOptimalReadLayout(m_params.readerStage);
1487 			const auto imageBarrier	= makeImageMemoryBarrier(writerAccessFlag, readerAccessFlag, resourceImgLayout, newLayout, resourceImg->get(), resourceImgSubresourceRange);
1488 
1489 			vkd.cmdPipelineBarrier(cmdBuffer, writerPipelineStage, readerPipelineStage, 0u, 0u, nullptr, 0u, nullptr, 1u, &imageBarrier);
1490 			resourceImgLayout = newLayout;
1491 		}
1492 		else
1493 		{
1494 			DE_ASSERT(false);
1495 		}
1496 	}
1497 	else
1498 	{
1499 		DE_ASSERT(false);
1500 	}
1501 
1502 	// Read resource from the reader stage copying it to the verification buffer.
1503 	if (m_params.readerStage == Stage::HOST)
1504 	{
1505 		// This needs to wait until we have submitted the command buffer. See below.
1506 	}
1507 	else if (m_params.readerStage == Stage::TRANSFER)
1508 	{
1509 		if (m_params.resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1510 		{
1511 			// This is a bit tricky because the resource buffer is in std140 format and the verification buffer is in std430 format.
1512 			std::vector<VkBufferCopy> regions;
1513 			regions.reserve(kBufferElements);
1514 			for (deUint32 i = 0; i < kBufferElements; ++i)
1515 			{
1516 				const VkBufferCopy region =
1517 				{
1518 					static_cast<VkDeviceSize>(i * sizeof(tcu::UVec4)),	//	VkDeviceSize	srcOffset;
1519 					static_cast<VkDeviceSize>(i * sizeof(deUint32)),	//	VkDeviceSize	dstOffset;
1520 					static_cast<VkDeviceSize>(sizeof(deUint32)),		//	VkDeviceSize	size;
1521 				};
1522 				regions.push_back(region);
1523 			}
1524 			vkd.cmdCopyBuffer(cmdBuffer, resourceBuffer->get(), verificationBuffer->get(), static_cast<deUint32>(regions.size()), regions.data());
1525 		}
1526 		else if (m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1527 		{
1528 			const auto bufferImageCopyRegion = makeBufferImageCopy(kImageExtent, imageSubresourceLayers);
1529 			vkd.cmdCopyImageToBuffer(cmdBuffer, resourceImg->get(), resourceImgLayout, verificationBuffer->get(), 1u, &bufferImageCopyRegion);
1530 		}
1531 		else
1532 		{
1533 			DE_ASSERT(false);
1534 		}
1535 	}
1536 	else
1537 	{
1538 		// All other stages use shaders to read the resource into the verification buffer.
1539 
1540 		// Descriptor set layout.
1541 		DescriptorSetLayoutBuilder dslBuilder;
1542 		dslBuilder.addBinding(m_params.resourceType, 1u, allStages, nullptr);					// Resource accessed in writers and readers.
1543 		if (readerNeedsAS)
1544 			dslBuilder.addBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1u, readerStages, nullptr);
1545 		dslBuilder.addBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, readerStages, nullptr);	// Verification buffer.
1546 		readerStageData.descriptorSetLayout = dslBuilder.build(vkd, device);
1547 
1548 		// Pipeline layout.
1549 		readerStageData.pipelineLayout = makePipelineLayout(vkd, device, readerStageData.descriptorSetLayout.get());
1550 
1551 		// Descriptor pool and set.
1552 		DescriptorPoolBuilder poolBuilder;
1553 		poolBuilder.addType(m_params.resourceType);
1554 		if (readerNeedsAS)
1555 			poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
1556 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1557 		readerStageData.descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1558 		readerStageData.descriptorSet = makeDescriptorSet(vkd, device, readerStageData.descriptorPool.get(), readerStageData.descriptorSetLayout.get());
1559 
1560 		// Update descriptor set.
1561 		updateDescriptorSet(vkd, device, cmdBuffer, alloc, m_params.resourceType, m_params.readerStage, readerStageData, resourceBuffer.get(), resourceImgView.get(), resourceImgLayout, readerNeedsAS, verificationBuffer.get());
1562 
1563 		if (m_params.readerStage == Stage::COMPUTE)
1564 		{
1565 			createComputePipeline(vkd, device, m_context, "reader_comp", readerStageData);
1566 			useComputePipeline(vkd, cmdBuffer, readerStageData);
1567 		}
1568 		else if (m_params.readerStage == Stage::FRAGMENT)
1569 		{
1570 			createGraphicsPipelineObjects(vkd, device, alloc, m_context, "reader_aux_vert", "reader_frag", readerStageData);
1571 			useGraphicsPipeline(vkd, cmdBuffer, readerStageData);
1572 		}
1573 		else
1574 		{
1575 			createRayTracingPipelineData(vkd, device, alloc, m_context, m_params.readerStage, readerStageData, shaderGroupHandleSize, shaderGroupBaseAlignment,
1576 										 "reader_aux_rgen", "reader_rgen", "reader_isect", "reader_ahit", "reader_chit", "reader_miss", "reader_callable");
1577 			useRayTracingPipeline(vkd, cmdBuffer, readerStageData);
1578 		}
1579 	}
1580 
1581 	// Sync verification buffer.
1582 	{
1583 		const auto readerVerificationFlags	= getWriterAccessFlag(m_params.readerStage);
1584 		const auto barrier					= makeBufferMemoryBarrier(readerVerificationFlags, VK_ACCESS_HOST_READ_BIT, verificationBuffer->get(), 0ull, VK_WHOLE_SIZE);
1585 		vkd.cmdPipelineBarrier(cmdBuffer, readerPipelineStage, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &barrier, 0u, nullptr);
1586 	}
1587 
1588 	// Submit all recorded commands.
1589 	endCommandBuffer(vkd, cmdBuffer);
1590 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1591 
1592 	invalidateAlloc(vkd, device, verificationBuffer->getAllocation());
1593 
1594 	// If the reader stage is the host, we have to wait until the commands have been submitted and the work has been done.
1595 	if (m_params.readerStage == Stage::HOST)
1596 	{
1597 		DE_ASSERT(m_params.resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || m_params.resourceType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1598 
1599 		auto& resourceBufferAlloc = resourceBuffer->getAllocation();
1600 		auto* resourceBufferPtr = resourceBufferAlloc.getHostPtr();
1601 
1602 		std::vector<tcu::UVec4> resourceData(kBufferElements);
1603 		invalidateAlloc(vkd, device, resourceBufferAlloc);
1604 		deMemcpy(resourceData.data(), resourceBufferPtr, static_cast<size_t>(kBufferElements) * sizeof(tcu::UVec4));
1605 
1606 		// Convert from std140 to std430 on the host.
1607 		std::vector<deUint32> verificationData(kBufferElements);
1608 		std::transform(begin(resourceData), end(resourceData), begin(verificationData),
1609 			[](const tcu::UVec4 &v) -> deUint32 { return v.x(); });
1610 
1611 		auto& verificationBufferAlloc = verificationBuffer->getAllocation();
1612 		auto* verificationBufferPtr = verificationBufferAlloc.getHostPtr();
1613 		deMemcpy(verificationBufferPtr, verificationData.data(), static_cast<size_t>(kBufferElements) * sizeof(deUint32));
1614 		flushAlloc(vkd, device, verificationBufferAlloc);
1615 	}
1616 
1617 	// Check verification buffer on the host.
1618 	{
1619 		auto& verificationAlloc = verificationBuffer->getAllocation();
1620 		auto* verificationPtr = verificationAlloc.getHostPtr();
1621 		std::vector<deUint32> verificationData(kBufferElements);
1622 		deMemcpy(verificationData.data(), verificationPtr, static_cast<size_t>(kBufferElements) * sizeof(deUint32));
1623 
1624 		for (size_t i = 0; i < verificationData.size(); ++i)
1625 		{
1626 			const auto&	value		= verificationData[i];
1627 			const auto	expected	= kValuesOffset + i;
1628 
1629 			if (value != expected)
1630 			{
1631 				std::ostringstream msg;
1632 				msg << "Unexpected value found at position " << i << ": found " << value << " and expected " << expected;
1633 				return tcu::TestStatus::fail(msg.str());
1634 			}
1635 		}
1636 	}
1637 
1638 	return tcu::TestStatus::pass("Pass");
1639 }
1640 
1641 } // anonymous.
1642 
createBarrierTests(tcu::TestContext & testCtx)1643 tcu::TestCaseGroup*	createBarrierTests(tcu::TestContext& testCtx)
1644 {
1645 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "barrier", "Tests involving pipeline barriers and ray tracing"));
1646 
1647 	const struct
1648 	{
1649 		VkDescriptorType	type;
1650 		const char*			name;
1651 	} resourceTypes[] =
1652 	{
1653 		{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,	"ubo"	},
1654 		{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,	"ssbo"	},
1655 		{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,		"simg"	},
1656 	};
1657 
1658 	const struct
1659 	{
1660 		Stage		stage;
1661 		const char*	name;
1662 	} stageList[] =
1663 	{
1664 		{ Stage::HOST,			"host"	},
1665 		{ Stage::TRANSFER,		"xfer"	},
1666 		{ Stage::RAYGEN,		"rgen"	},
1667 		{ Stage::INTERSECT,		"isec"	},
1668 		{ Stage::ANY_HIT,		"ahit"	},
1669 		{ Stage::CLOSEST_HIT,	"chit"	},
1670 		{ Stage::MISS,			"miss"	},
1671 		{ Stage::CALLABLE,		"call"	},
1672 		{ Stage::COMPUTE,		"comp"	},
1673 		{ Stage::FRAGMENT,		"frag"	},
1674 	};
1675 
1676 	const struct
1677 	{
1678 		BarrierType	barrierType;
1679 		const char*	name;
1680 	} barrierTypes[] =
1681 	{
1682 		{ BarrierType::GENERAL,		"memory_barrier"	},
1683 		{ BarrierType::SPECIFIC,	"specific_barrier"	},
1684 	};
1685 
1686 	for (int resourceTypeIdx = 0; resourceTypeIdx < DE_LENGTH_OF_ARRAY(resourceTypes); ++resourceTypeIdx)
1687 	{
1688 		de::MovePtr<tcu::TestCaseGroup> resourceTypeGroup(new tcu::TestCaseGroup(testCtx, resourceTypes[resourceTypeIdx].name, ""));
1689 
1690 		for (int barrierTypeIdx = 0; barrierTypeIdx < DE_LENGTH_OF_ARRAY(barrierTypes); ++barrierTypeIdx)
1691 		{
1692 			de::MovePtr<tcu::TestCaseGroup> barrierTypeGroup(new tcu::TestCaseGroup(testCtx, barrierTypes[barrierTypeIdx].name, ""));
1693 
1694 			for (int writerStageIdx = 0; writerStageIdx < DE_LENGTH_OF_ARRAY(stageList); ++writerStageIdx)
1695 			for (int readerStageIdx = 0; readerStageIdx < DE_LENGTH_OF_ARRAY(stageList); ++readerStageIdx)
1696 			{
1697 				const auto resourceType	= resourceTypes[resourceTypeIdx].type;
1698 				const auto barrierType	= barrierTypes[barrierTypeIdx].barrierType;
1699 				const auto readerStage	= stageList[readerStageIdx].stage;
1700 				const auto writerStage	= stageList[writerStageIdx].stage;
1701 
1702 				// Skip tests that do not involve ray tracing.
1703 				if (!isRayTracingStage(readerStage) && !isRayTracingStage(writerStage))
1704 					continue;
1705 
1706 				// Skip tests which require host acess to images.
1707 				if (resourceType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE && (writerStage == Stage::HOST || readerStage == Stage::HOST))
1708 					continue;
1709 
1710 				// Skip tests that would require writes from shaders to an UBO.
1711 				if (resourceType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER && writerStage != Stage::HOST && writerStage != Stage::TRANSFER)
1712 					continue;
1713 
1714 				const std::string testName = std::string("from_") + stageList[writerStageIdx].name + "_to_" + stageList[readerStageIdx].name;
1715 				barrierTypeGroup->addChild(new BarrierTestCase(testCtx, testName, "", TestParams(resourceType, writerStage, readerStage, barrierType)));
1716 			}
1717 			resourceTypeGroup->addChild(barrierTypeGroup.release());
1718 		}
1719 		group->addChild(resourceTypeGroup.release());
1720 	}
1721 	return group.release();
1722 }
1723 
1724 } // RayTracing
1725 } // vkt
1726