• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Synchronization operation abstraction
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSynchronizationOperation.hpp"
25 #include "vkDefs.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vkRef.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkBarrierUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 #include "deUniquePtr.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include <vector>
42 #include <sstream>
43 
44 namespace vkt
45 {
46 namespace synchronization
47 {
48 namespace
49 {
50 using namespace vk;
51 
52 enum Constants
53 {
54 	MAX_IMAGE_DIMENSION_2D	= 0x1000u,
55 	MAX_UBO_RANGE			= 0x4000u,
56 	MAX_UPDATE_BUFFER_SIZE	= 0x10000u,
57 };
58 
59 enum BufferType
60 {
61 	BUFFER_TYPE_UNIFORM,
62 	BUFFER_TYPE_STORAGE,
63 };
64 
65 enum AccessMode
66 {
67 	ACCESS_MODE_READ,
68 	ACCESS_MODE_WRITE,
69 };
70 
71 enum PipelineType
72 {
73 	PIPELINE_TYPE_GRAPHICS,
74 	PIPELINE_TYPE_COMPUTE,
75 };
76 
77 static const char* const s_perVertexBlock =	"gl_PerVertex {\n"
78 											"    vec4 gl_Position;\n"
79 											"}";
80 
81 static const SyncInfo emptySyncInfo =
82 {
83 	0,							// VkPipelineStageFlags		stageMask;
84 	0,							// VkAccessFlags			accessMask;
85 	VK_IMAGE_LAYOUT_UNDEFINED,	// VkImageLayout			imageLayout;
86 };
87 
getShaderStageName(VkShaderStageFlagBits stage)88 std::string getShaderStageName(VkShaderStageFlagBits stage)
89 {
90 	switch (stage)
91 	{
92 		default:
93 			DE_FATAL("Unhandled stage!");
94 			return "";
95 		case VK_SHADER_STAGE_COMPUTE_BIT:
96 			return "compute";
97 		case VK_SHADER_STAGE_FRAGMENT_BIT:
98 			return "fragment";
99 		case VK_SHADER_STAGE_VERTEX_BIT:
100 			return "vertex";
101 		case VK_SHADER_STAGE_GEOMETRY_BIT:
102 			return "geometry";
103 		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
104 			return "tess_control";
105 		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
106 			return "tess_eval";
107 	}
108 }
109 
110 //! A pipeline that can be embedded inside an operation.
111 class Pipeline
112 {
113 public:
~Pipeline(void)114 	virtual			~Pipeline		(void) {}
115 	virtual void	recordCommands	(OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet) = 0;
116 };
117 
118 //! Vertex data that covers the whole viewport with two triangles.
119 class VertexGrid
120 {
121 public:
VertexGrid(OperationContext & context)122 	VertexGrid (OperationContext& context)
123 		: m_vertexFormat (VK_FORMAT_R32G32B32A32_SFLOAT)
124 		, m_vertexStride (tcu::getPixelSize(mapVkFormat(m_vertexFormat)))
125 	{
126 		const DeviceInterface&	vk			= context.getDeviceInterface();
127 		const VkDevice			device		= context.getDevice();
128 		Allocator&				allocator	= context.getAllocator();
129 
130 		// Vertex positions
131 		{
132 			m_vertexData.push_back(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
133 			m_vertexData.push_back(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
134 			m_vertexData.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
135 
136 			m_vertexData.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
137 			m_vertexData.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
138 			m_vertexData.push_back(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
139 		}
140 
141 		{
142 			const VkDeviceSize vertexDataSizeBytes = m_vertexData.size() * sizeof(m_vertexData[0]);
143 
144 			m_vertexBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
145 			DE_ASSERT(sizeof(m_vertexData[0]) == m_vertexStride);
146 
147 			{
148 				const Allocation& alloc = m_vertexBuffer->getAllocation();
149 
150 				deMemcpy(alloc.getHostPtr(), &m_vertexData[0], static_cast<std::size_t>(vertexDataSizeBytes));
151 				flushAlloc(vk, device, alloc);
152 			}
153 		}
154 
155 		// Indices
156 		{
157 			const VkDeviceSize	indexBufferSizeBytes	= sizeof(deUint32) * m_vertexData.size();
158 			const deUint32		numIndices				= static_cast<deUint32>(m_vertexData.size());
159 
160 			m_indexBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, makeBufferCreateInfo(indexBufferSizeBytes, VK_BUFFER_USAGE_INDEX_BUFFER_BIT), MemoryRequirement::HostVisible));
161 
162 			{
163 				const Allocation&	alloc	= m_indexBuffer->getAllocation();
164 				deUint32* const		pData	= static_cast<deUint32*>(alloc.getHostPtr());
165 
166 				for (deUint32 i = 0; i < numIndices; ++i)
167 					pData[i] = i;
168 
169 				flushAlloc(vk, device, alloc);
170 			}
171 		}
172 	}
173 
getVertexFormat(void) const174 	VkFormat	getVertexFormat		(void) const { return m_vertexFormat; }
getVertexStride(void) const175 	deUint32	getVertexStride		(void) const { return m_vertexStride; }
getIndexType(void) const176 	VkIndexType getIndexType		(void) const { return VK_INDEX_TYPE_UINT32; }
getNumVertices(void) const177 	deUint32	getNumVertices		(void) const { return static_cast<deUint32>(m_vertexData.size()); }
getNumIndices(void) const178 	deUint32	getNumIndices		(void) const { return getNumVertices(); }
getVertexBuffer(void) const179 	VkBuffer	getVertexBuffer		(void) const { return **m_vertexBuffer; }
getIndexBuffer(void) const180 	VkBuffer	getIndexBuffer		(void) const { return **m_indexBuffer; }
181 
182 private:
183 	const VkFormat				m_vertexFormat;
184 	const deUint32				m_vertexStride;
185 	std::vector<tcu::Vec4>		m_vertexData;
186 	de::MovePtr<Buffer>			m_vertexBuffer;
187 	de::MovePtr<Buffer>			m_indexBuffer;
188 };
189 
190 //! Add flags for all shader stages required to support a particular stage (e.g. fragment requires vertex as well).
getRequiredStages(const VkShaderStageFlagBits stage)191 VkShaderStageFlags getRequiredStages (const VkShaderStageFlagBits stage)
192 {
193 	VkShaderStageFlags flags = 0;
194 
195 	DE_ASSERT(stage == VK_SHADER_STAGE_COMPUTE_BIT || (stage & VK_SHADER_STAGE_COMPUTE_BIT) == 0);
196 
197 	if (stage & VK_SHADER_STAGE_ALL_GRAPHICS)
198 		flags |= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
199 
200 	if (stage & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
201 		flags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
202 
203 	if (stage & VK_SHADER_STAGE_GEOMETRY_BIT)
204 		flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
205 
206 	if (stage & VK_SHADER_STAGE_COMPUTE_BIT)
207 		flags |= VK_SHADER_STAGE_COMPUTE_BIT;
208 
209 	return flags;
210 }
211 
212 //! Check that SSBO read/write is available and that all shader stages are supported.
requireFeaturesForSSBOAccess(OperationContext & context,const VkShaderStageFlags usedStages)213 void requireFeaturesForSSBOAccess (OperationContext& context, const VkShaderStageFlags usedStages)
214 {
215 	const InstanceInterface&	vki			= context.getInstanceInterface();
216 	const VkPhysicalDevice		physDevice	= context.getPhysicalDevice();
217 	FeatureFlags				flags		= (FeatureFlags)0;
218 
219 	if (usedStages & VK_SHADER_STAGE_FRAGMENT_BIT)
220 		flags |= FEATURE_FRAGMENT_STORES_AND_ATOMICS;
221 
222 	if (usedStages & (VK_SHADER_STAGE_ALL_GRAPHICS & (~VK_SHADER_STAGE_FRAGMENT_BIT)))
223 		flags |= FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS;
224 
225 	if (usedStages & VK_SHADER_STAGE_GEOMETRY_BIT)
226 		flags |= FEATURE_GEOMETRY_SHADER;
227 
228 	if (usedStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
229 		flags |= FEATURE_TESSELLATION_SHADER;
230 
231 	requireFeatures(vki, physDevice, flags);
232 }
233 
getHostBufferData(const OperationContext & context,const Buffer & hostBuffer,const VkDeviceSize size)234 Data getHostBufferData (const OperationContext& context, const Buffer& hostBuffer, const VkDeviceSize size)
235 {
236 	const DeviceInterface&	vk		= context.getDeviceInterface();
237 	const VkDevice			device	= context.getDevice();
238 	const Allocation&		alloc	= hostBuffer.getAllocation();
239 	const Data				data	=
240 	{
241 		static_cast<std::size_t>(size),					// std::size_t		size;
242 		static_cast<deUint8*>(alloc.getHostPtr()),		// const deUint8*	data;
243 	};
244 
245 	invalidateAlloc(vk, device, alloc);
246 
247 	return data;
248 }
249 
setHostBufferData(const OperationContext & context,const Buffer & hostBuffer,const Data & data)250 void setHostBufferData (const OperationContext& context, const Buffer& hostBuffer, const Data& data)
251 {
252 	const DeviceInterface&	vk		= context.getDeviceInterface();
253 	const VkDevice			device	= context.getDevice();
254 	const Allocation&		alloc	= hostBuffer.getAllocation();
255 
256 	deMemcpy(alloc.getHostPtr(), data.data, data.size);
257 	flushAlloc(vk, device, alloc);
258 }
259 
assertValidShaderStage(const VkShaderStageFlagBits stage)260 void assertValidShaderStage (const VkShaderStageFlagBits stage)
261 {
262 	switch (stage)
263 	{
264 		case VK_SHADER_STAGE_VERTEX_BIT:
265 		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
266 		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
267 		case VK_SHADER_STAGE_GEOMETRY_BIT:
268 		case VK_SHADER_STAGE_FRAGMENT_BIT:
269 		case VK_SHADER_STAGE_COMPUTE_BIT:
270 			// OK
271 			break;
272 
273 		default:
274 			DE_FATAL("Invalid shader stage");
275 			break;
276 	}
277 }
278 
pipelineStageFlagsFromShaderStageFlagBits(const VkShaderStageFlagBits shaderStage)279 VkPipelineStageFlags pipelineStageFlagsFromShaderStageFlagBits (const VkShaderStageFlagBits shaderStage)
280 {
281 	switch (shaderStage)
282 	{
283 		case VK_SHADER_STAGE_VERTEX_BIT:					return VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR;
284 		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:		return VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR;
285 		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:	return VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR;
286 		case VK_SHADER_STAGE_GEOMETRY_BIT:					return VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR;
287 		case VK_SHADER_STAGE_FRAGMENT_BIT:					return VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR;
288 		case VK_SHADER_STAGE_COMPUTE_BIT:					return VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR;
289 
290 		// Other usages are probably an error, so flag that.
291 		default:
292 			DE_FATAL("Invalid shader stage");
293 			return (VkPipelineStageFlags)0;
294 	}
295 }
296 
297 //! Fill destination buffer with a repeating pattern.
fillPattern(void * const pData,const VkDeviceSize size,bool useIndexPattern=false)298 void fillPattern (void* const pData, const VkDeviceSize size, bool useIndexPattern = false)
299 {
300 	// There are two pattern options - most operations use primePattern,
301 	// indexPattern is only needed for testing vertex index bufffer.
302 	static const deUint8	primePattern[]	= { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
303 	static const deUint32	indexPattern[]	= { 0, 1, 2, 3, 4 };
304 
305 	const deUint8*			pattern			= (useIndexPattern ? reinterpret_cast<const deUint8*>(indexPattern)
306 															   : primePattern);
307 	const deUint32			patternSize		= static_cast<deUint32>(useIndexPattern
308 															   ? DE_LENGTH_OF_ARRAY(indexPattern)*sizeof(deUint32)
309 															   : DE_LENGTH_OF_ARRAY(primePattern));
310 	deUint8* const			pBytes			= static_cast<deUint8*>(pData);
311 
312 	for (deUint32 i = 0; i < size; ++i)
313 		pBytes[i] = pattern[i % patternSize];
314 }
315 
316 //! Get size in bytes of a pixel buffer with given extent.
getPixelBufferSize(const VkFormat format,const VkExtent3D & extent)317 VkDeviceSize getPixelBufferSize (const VkFormat format, const VkExtent3D& extent)
318 {
319 	const int pixelSize = tcu::getPixelSize(mapVkFormat(format));
320 	return (pixelSize * extent.width * extent.height * extent.depth);
321 }
322 
323 //! Determine the size of a 2D image that can hold sizeBytes data.
get2DImageExtentWithSize(const VkDeviceSize sizeBytes,const deUint32 pixelSize)324 VkExtent3D get2DImageExtentWithSize (const VkDeviceSize sizeBytes, const deUint32 pixelSize)
325 {
326 	const deUint32 size = static_cast<deUint32>(sizeBytes / pixelSize);
327 
328 	DE_ASSERT(size <= MAX_IMAGE_DIMENSION_2D * MAX_IMAGE_DIMENSION_2D);
329 
330 	return makeExtent3D(
331 		std::min(size, static_cast<deUint32>(MAX_IMAGE_DIMENSION_2D)),
332 		(size / MAX_IMAGE_DIMENSION_2D) + (size % MAX_IMAGE_DIMENSION_2D != 0 ? 1u : 0u),
333 		1u);
334 }
335 
makeClearValue(const VkFormat format)336 VkClearValue makeClearValue (const VkFormat format)
337 {
338 	if (isDepthStencilFormat(format))
339 		return makeClearValueDepthStencil(0.4f, 21u);
340 	else
341 	{
342 		if (isIntFormat(format) || isUintFormat(format))
343 			return makeClearValueColorU32(8u, 16u, 24u, 32u);
344 		else
345 			return makeClearValueColorF32(0.25f, 0.49f, 0.75f, 1.0f);
346 	}
347 }
348 
clearPixelBuffer(tcu::PixelBufferAccess & pixels,const VkClearValue & clearValue)349 void clearPixelBuffer (tcu::PixelBufferAccess& pixels, const VkClearValue& clearValue)
350 {
351 	const tcu::TextureFormat		format			= pixels.getFormat();
352 	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(format.type);
353 
354 	if (format.order == tcu::TextureFormat::D)
355 	{
356 		for (int z = 0; z < pixels.getDepth(); z++)
357 		for (int y = 0; y < pixels.getHeight(); y++)
358 		for (int x = 0; x < pixels.getWidth(); x++)
359 			pixels.setPixDepth(clearValue.depthStencil.depth, x, y, z);
360 	}
361 	else if (format.order == tcu::TextureFormat::S)
362 	{
363 		for (int z = 0; z < pixels.getDepth(); z++)
364 		for (int y = 0; y < pixels.getHeight(); y++)
365 		for (int x = 0; x < pixels.getWidth(); x++)
366 			pixels.setPixStencil(clearValue.depthStencil.stencil, x, y, z);
367 	}
368 	else if (format.order == tcu::TextureFormat::DS)
369 	{
370 		for (int z = 0; z < pixels.getDepth(); z++)
371 		for (int y = 0; y < pixels.getHeight(); y++)
372 		for (int x = 0; x < pixels.getWidth(); x++)
373 		{
374 			pixels.setPixDepth(clearValue.depthStencil.depth, x, y, z);
375 			pixels.setPixStencil(clearValue.depthStencil.stencil, x, y, z);
376 		}
377 	}
378 	else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
379 	{
380 		const tcu::UVec4 color (clearValue.color.uint32);
381 
382 		for (int z = 0; z < pixels.getDepth(); z++)
383 		for (int y = 0; y < pixels.getHeight(); y++)
384 		for (int x = 0; x < pixels.getWidth(); x++)
385 			pixels.setPixel(color, x, y, z);
386 	}
387 	else
388 	{
389 		const tcu::Vec4 color (clearValue.color.float32);
390 
391 		for (int z = 0; z < pixels.getDepth(); z++)
392 		for (int y = 0; y < pixels.getHeight(); y++)
393 		for (int x = 0; x < pixels.getWidth(); x++)
394 			pixels.setPixel(color, x, y, z);
395 	}
396 }
397 
getImageViewType(const VkImageType imageType)398 VkImageViewType getImageViewType (const VkImageType imageType)
399 {
400 	switch (imageType)
401 	{
402 		case VK_IMAGE_TYPE_1D:		return VK_IMAGE_VIEW_TYPE_1D;
403 		case VK_IMAGE_TYPE_2D:		return VK_IMAGE_VIEW_TYPE_2D;
404 		case VK_IMAGE_TYPE_3D:		return VK_IMAGE_VIEW_TYPE_3D;
405 
406 		default:
407 			DE_FATAL("Unknown image type");
408 			return VK_IMAGE_VIEW_TYPE_LAST;
409 	}
410 }
411 
getShaderImageType(const VkFormat format,const VkImageType imageType)412 std::string getShaderImageType (const VkFormat format, const VkImageType imageType)
413 {
414 	const tcu::TextureFormat	texFormat	= mapVkFormat(format);
415 	const std::string			formatPart	= tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
416 											  tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
417 	switch (imageType)
418 	{
419 		case VK_IMAGE_TYPE_1D:	return formatPart + "image1D";
420 		case VK_IMAGE_TYPE_2D:	return formatPart + "image2D";
421 		case VK_IMAGE_TYPE_3D:	return formatPart + "image3D";
422 
423 		default:
424 			DE_FATAL("Unknown image type");
425 			return "";
426 	}
427 }
428 
getShaderImageFormatQualifier(const VkFormat format)429 std::string getShaderImageFormatQualifier (const VkFormat format)
430 {
431 	const tcu::TextureFormat	texFormat	= mapVkFormat(format);
432 	const char*					orderPart	= DE_NULL;
433 	const char*					typePart	= DE_NULL;
434 
435 	switch (texFormat.order)
436 	{
437 		case tcu::TextureFormat::R:		orderPart = "r";	break;
438 		case tcu::TextureFormat::RG:	orderPart = "rg";	break;
439 		case tcu::TextureFormat::RGB:	orderPart = "rgb";	break;
440 		case tcu::TextureFormat::RGBA:	orderPart = "rgba";	break;
441 
442 		default:
443 			DE_FATAL("Unksupported texture channel order");
444 			break;
445 	}
446 
447 	switch (texFormat.type)
448 	{
449 		case tcu::TextureFormat::FLOAT:				typePart = "32f";		break;
450 		case tcu::TextureFormat::HALF_FLOAT:		typePart = "16f";		break;
451 
452 		case tcu::TextureFormat::UNSIGNED_INT32:	typePart = "32ui";		break;
453 		case tcu::TextureFormat::UNSIGNED_INT16:	typePart = "16ui";		break;
454 		case tcu::TextureFormat::UNSIGNED_INT8:		typePart = "8ui";		break;
455 
456 		case tcu::TextureFormat::SIGNED_INT32:		typePart = "32i";		break;
457 		case tcu::TextureFormat::SIGNED_INT16:		typePart = "16i";		break;
458 		case tcu::TextureFormat::SIGNED_INT8:		typePart = "8i";		break;
459 
460 		case tcu::TextureFormat::UNORM_INT16:		typePart = "16";		break;
461 		case tcu::TextureFormat::UNORM_INT8:		typePart = "8";			break;
462 
463 		case tcu::TextureFormat::SNORM_INT16:		typePart = "16_snorm";	break;
464 		case tcu::TextureFormat::SNORM_INT8:		typePart = "8_snorm";	break;
465 
466 		default:
467 			DE_FATAL("Unksupported texture channel type");
468 			break;
469 	}
470 
471 	return std::string(orderPart) + typePart;
472 }
473 
474 namespace FillUpdateBuffer
475 {
476 
477 enum BufferOp
478 {
479 	BUFFER_OP_FILL,
480 	BUFFER_OP_UPDATE,
481 	BUFFER_OP_UPDATE_WITH_INDEX_PATTERN,
482 };
483 
484 class Implementation : public Operation
485 {
486 public:
Implementation(OperationContext & context,Resource & resource,const BufferOp bufferOp)487 	Implementation (OperationContext& context, Resource& resource, const BufferOp bufferOp)
488 		: m_context		(context)
489 		, m_resource	(resource)
490 		, m_fillValue	(0x13)
491 		, m_bufferOp	(bufferOp)
492 	{
493 		DE_ASSERT((m_resource.getBuffer().size % sizeof(deUint32)) == 0);
494 		DE_ASSERT(m_bufferOp == BUFFER_OP_FILL || m_resource.getBuffer().size <= MAX_UPDATE_BUFFER_SIZE);
495 
496 		m_data.resize(static_cast<size_t>(m_resource.getBuffer().size));
497 
498 		if (m_bufferOp == BUFFER_OP_FILL)
499 		{
500 			const std::size_t	size	= m_data.size() / sizeof(m_fillValue);
501 			deUint32* const		pData	= reinterpret_cast<deUint32*>(&m_data[0]);
502 
503 			for (deUint32 i = 0; i < size; ++i)
504 				pData[i] = m_fillValue;
505 		}
506 		else if (m_bufferOp == BUFFER_OP_UPDATE)
507 		{
508 			fillPattern(&m_data[0], m_data.size());
509 		}
510 		else if(m_bufferOp == BUFFER_OP_UPDATE_WITH_INDEX_PATTERN)
511 		{
512 			fillPattern(&m_data[0], m_data.size(), true);
513 		}
514 	}
515 
recordCommands(const VkCommandBuffer cmdBuffer)516 	void recordCommands (const VkCommandBuffer cmdBuffer)
517 	{
518 		const DeviceInterface&	vk	= m_context.getDeviceInterface();
519 
520 		if (m_bufferOp == BUFFER_OP_FILL)
521 		{
522 			vk.cmdFillBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, m_fillValue);
523 
524 			SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
525 			const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
526 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,					// VkPipelineStageFlags2KHR			srcStageMask
527 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,						// VkAccessFlags2KHR				srcAccessMask
528 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,					// VkPipelineStageFlags2KHR			dstStageMask
529 				VK_ACCESS_2_TRANSFER_READ_BIT_KHR,						// VkAccessFlags2KHR				dstAccessMask
530 				m_resource.getBuffer().handle,							// VkBuffer							buffer
531 				0u,														// VkDeviceSize						offset
532 				m_resource.getBuffer().size								// VkDeviceSize						size
533 			);
534 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
535 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
536 		}
537 		else
538 			vk.cmdUpdateBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, reinterpret_cast<deUint32*>(&m_data[0]));
539 	}
540 
getInSyncInfo(void) const541 	SyncInfo getInSyncInfo (void) const
542 	{
543 		return emptySyncInfo;
544 	}
545 
getOutSyncInfo(void) const546 	SyncInfo getOutSyncInfo (void) const
547 	{
548 		const SyncInfo syncInfo =
549 		{
550 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
551 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,		// VkAccessFlags			accessMask;
552 			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			imageLayout;
553 		};
554 
555 		return syncInfo;
556 	}
557 
getData(void) const558 	Data getData (void) const
559 	{
560 		const Data data =
561 		{
562 			m_data.size(),		// std::size_t		size;
563 			&m_data[0],			// const deUint8*	data;
564 		};
565 		return data;
566 	}
567 
setData(const Data & data)568 	void setData (const Data& data)
569 	{
570 		deMemcpy(&m_data[0], data.data, data.size);
571 	}
572 
573 private:
574 	OperationContext&		m_context;
575 	Resource&				m_resource;
576 	std::vector<deUint8>	m_data;
577 	const deUint32			m_fillValue;
578 	const BufferOp			m_bufferOp;
579 };
580 
581 class Support : public OperationSupport
582 {
583 public:
Support(const ResourceDescription & resourceDesc,const BufferOp bufferOp)584 	Support (const ResourceDescription& resourceDesc, const BufferOp bufferOp)
585 		: m_resourceDesc	(resourceDesc)
586 		, m_bufferOp		(bufferOp)
587 	{
588 		DE_ASSERT(m_bufferOp == BUFFER_OP_FILL || m_bufferOp == BUFFER_OP_UPDATE || m_bufferOp == BUFFER_OP_UPDATE_WITH_INDEX_PATTERN);
589 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER || m_resourceDesc.type == RESOURCE_TYPE_INDEX_BUFFER);
590 	}
591 
getInResourceUsageFlags(void) const592 	deUint32 getInResourceUsageFlags (void) const
593 	{
594 		return 0;
595 	}
596 
getOutResourceUsageFlags(void) const597 	deUint32 getOutResourceUsageFlags (void) const
598 	{
599 		return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
600 	}
601 
getQueueFlags(const OperationContext & context) const602 	VkQueueFlags getQueueFlags (const OperationContext& context) const
603 	{
604 		if (m_bufferOp == BUFFER_OP_FILL && !context.isDeviceFunctionalitySupported("VK_KHR_maintenance1"))
605 		{
606 			return VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT;
607 		}
608 
609 		return VK_QUEUE_TRANSFER_BIT;
610 	}
611 
build(OperationContext & context,Resource & resource) const612 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
613 	{
614 		return de::MovePtr<Operation>(new Implementation(context, resource, m_bufferOp));
615 	}
616 
build(OperationContext &,Resource &,Resource &) const617 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
618 	{
619 		DE_ASSERT(0);
620 		return de::MovePtr<Operation>();
621 	}
622 
623 private:
624 	const ResourceDescription	m_resourceDesc;
625 	const BufferOp				m_bufferOp;
626 };
627 
628 } // FillUpdateBuffer ns
629 
630 namespace CopyBuffer
631 {
632 
633 class Implementation : public Operation
634 {
635 public:
Implementation(OperationContext & context,Resource & resource,const AccessMode mode)636 	Implementation (OperationContext& context, Resource& resource, const AccessMode mode)
637 		: m_context		(context)
638 		, m_resource	(resource)
639 		, m_mode		(mode)
640 	{
641 		const DeviceInterface&		vk				= m_context.getDeviceInterface();
642 		const VkDevice				device			= m_context.getDevice();
643 		Allocator&					allocator		= m_context.getAllocator();
644 		const VkBufferUsageFlags	hostBufferUsage	= (m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
645 
646 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, hostBufferUsage), MemoryRequirement::HostVisible));
647 
648 		const Allocation& alloc = m_hostBuffer->getAllocation();
649 
650 		if (m_mode == ACCESS_MODE_READ)
651 			deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_resource.getBuffer().size));
652 		else
653 			fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
654 
655 		flushAlloc(vk, device, alloc);
656 	}
657 
recordCommands(const VkCommandBuffer cmdBuffer)658 	void recordCommands (const VkCommandBuffer cmdBuffer)
659 	{
660 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
661 		const VkBufferCopy			copyRegion				= makeBufferCopy(0u, 0u, m_resource.getBuffer().size);
662 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
663 
664 		if (m_mode == ACCESS_MODE_READ)
665 		{
666 			vk.cmdCopyBuffer(cmdBuffer, m_resource.getBuffer().handle, **m_hostBuffer, 1u, &copyRegion);
667 
668 			// Insert a barrier so copied data is available to the host
669 			const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
670 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,					// VkPipelineStageFlags2KHR			srcStageMask
671 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,						// VkAccessFlags2KHR				srcAccessMask
672 				VK_PIPELINE_STAGE_2_HOST_BIT_KHR,						// VkPipelineStageFlags2KHR			dstStageMask
673 				VK_ACCESS_2_HOST_READ_BIT_KHR,							// VkAccessFlags2KHR				dstAccessMask
674 				**m_hostBuffer,											// VkBuffer							buffer
675 				0u,														// VkDeviceSize						offset
676 				m_resource.getBuffer().size								// VkDeviceSize						size
677 			);
678 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
679 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
680 		}
681 		else
682 		{
683 			// Insert a barrier so buffer data is available to the device
684 			//const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
685 			//	VK_PIPELINE_STAGE_2_HOST_BIT_KHR,						// VkPipelineStageFlags2KHR			srcStageMask
686 			//	VK_ACCESS_2_HOST_WRITE_BIT_KHR,							// VkAccessFlags2KHR				srcAccessMask
687 			//	VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,					// VkPipelineStageFlags2KHR			dstStageMask
688 			//	VK_ACCESS_2_TRANSFER_READ_BIT_KHR,						// VkAccessFlags2KHR				dstAccessMask
689 			//	**m_hostBuffer,											// VkBuffer							buffer
690 			//	0u,														// VkDeviceSize						offset
691 			//	m_resource.getBuffer().size								// VkDeviceSize						size
692 			//);
693 			//VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
694 			//synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
695 
696 			vk.cmdCopyBuffer(cmdBuffer, **m_hostBuffer, m_resource.getBuffer().handle, 1u, &copyRegion);
697 		}
698 	}
699 
getInSyncInfo(void) const700 	SyncInfo getInSyncInfo (void) const
701 	{
702 		const VkAccessFlags access		= (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_TRANSFER_READ_BIT_KHR : 0);
703 		const SyncInfo		syncInfo	=
704 		{
705 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
706 			access,									// VkAccessFlags			accessMask;
707 			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			imageLayout;
708 		};
709 		return syncInfo;
710 	}
711 
getOutSyncInfo(void) const712 	SyncInfo getOutSyncInfo (void) const
713 	{
714 		const VkAccessFlags access		= (m_mode == ACCESS_MODE_WRITE ? VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR : 0);
715 		const SyncInfo		syncInfo	=
716 		{
717 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
718 			access,									// VkAccessFlags			accessMask;
719 			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			imageLayout;
720 		};
721 		return syncInfo;
722 	}
723 
getData(void) const724 	Data getData (void) const
725 	{
726 		return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
727 	}
728 
setData(const Data & data)729 	void setData (const Data& data)
730 	{
731 		DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
732 		setHostBufferData(m_context, *m_hostBuffer, data);
733 	}
734 
735 private:
736 	OperationContext&		m_context;
737 	Resource&				m_resource;
738 	const AccessMode		m_mode;
739 	de::MovePtr<Buffer>		m_hostBuffer;
740 };
741 
742 class Support : public OperationSupport
743 {
744 public:
Support(const ResourceDescription & resourceDesc,const AccessMode mode)745 	Support (const ResourceDescription& resourceDesc, const AccessMode mode)
746 		: m_mode			(mode)
747 	{
748 		DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_BUFFER);
749 		DE_UNREF(resourceDesc);
750 	}
751 
getInResourceUsageFlags(void) const752 	deUint32 getInResourceUsageFlags (void) const
753 	{
754 		return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0;
755 	}
756 
getOutResourceUsageFlags(void) const757 	deUint32 getOutResourceUsageFlags (void) const
758 	{
759 		return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0;
760 	}
761 
getQueueFlags(const OperationContext & context) const762 	VkQueueFlags getQueueFlags (const OperationContext& context) const
763 	{
764 		DE_UNREF(context);
765 		return VK_QUEUE_TRANSFER_BIT;
766 	}
767 
build(OperationContext & context,Resource & resource) const768 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
769 	{
770 		return de::MovePtr<Operation>(new Implementation(context, resource, m_mode));
771 	}
772 
build(OperationContext &,Resource &,Resource &) const773 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
774 	{
775 		DE_ASSERT(0);
776 		return de::MovePtr<Operation>();
777 	}
778 
779 private:
780 	const AccessMode	m_mode;
781 };
782 
783 class CopyImplementation : public Operation
784 {
785 public:
CopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)786 	CopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
787 		: m_context		(context)
788 		, m_inResource	(inResource)
789 		, m_outResource	(outResource)
790 	{
791 	}
792 
recordCommands(const VkCommandBuffer cmdBuffer)793 	void recordCommands (const VkCommandBuffer cmdBuffer)
794 	{
795 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
796 		const VkBufferCopy		copyRegion	= makeBufferCopy(0u, 0u, m_inResource.getBuffer().size);
797 
798 		vk.cmdCopyBuffer(cmdBuffer, m_inResource.getBuffer().handle, m_outResource.getBuffer().handle, 1u, &copyRegion);
799 	}
800 
getInSyncInfo(void) const801 	SyncInfo getInSyncInfo (void) const
802 	{
803 		const SyncInfo		syncInfo	=
804 		{
805 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
806 			VK_ACCESS_2_TRANSFER_READ_BIT_KHR,		// VkAccessFlags			accessMask;
807 			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			imageLayout;
808 		};
809 		return syncInfo;
810 	}
811 
getOutSyncInfo(void) const812 	SyncInfo getOutSyncInfo (void) const
813 	{
814 		const SyncInfo		syncInfo	=
815 		{
816 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
817 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,		// VkAccessFlags			accessMask;
818 			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			imageLayout;
819 		};
820 		return syncInfo;
821 	}
822 
getData(void) const823 	Data getData (void) const
824 	{
825 		Data data = { 0, DE_NULL };
826 		return data;
827 	}
828 
setData(const Data &)829 	void setData (const Data&)
830 	{
831 		DE_ASSERT(0);
832 	}
833 
834 private:
835 	OperationContext&		m_context;
836 	Resource&				m_inResource;
837 	Resource&				m_outResource;
838 	de::MovePtr<Buffer>		m_hostBuffer;
839 };
840 
841 class CopySupport : public OperationSupport
842 {
843 public:
CopySupport(const ResourceDescription & resourceDesc)844 	CopySupport (const ResourceDescription& resourceDesc)
845 	{
846 		DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_BUFFER);
847 		DE_UNREF(resourceDesc);
848 	}
849 
getInResourceUsageFlags(void) const850 	deUint32 getInResourceUsageFlags (void) const
851 	{
852 		return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
853 	}
854 
getOutResourceUsageFlags(void) const855 	deUint32 getOutResourceUsageFlags (void) const
856 	{
857 		return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
858 	}
859 
getQueueFlags(const OperationContext & context) const860 	VkQueueFlags getQueueFlags (const OperationContext& context) const
861 	{
862 		DE_UNREF(context);
863 		return VK_QUEUE_TRANSFER_BIT;
864 	}
865 
build(OperationContext &,Resource &) const866 	de::MovePtr<Operation> build (OperationContext&, Resource&) const
867 	{
868 		DE_ASSERT(0);
869 		return de::MovePtr<Operation>();
870 	}
871 
build(OperationContext & context,Resource & inResource,Resource & outResource) const872 	de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
873 	{
874 		return de::MovePtr<Operation>(new CopyImplementation(context, inResource, outResource));
875 	}
876 };
877 
878 } // CopyBuffer ns
879 
880 namespace CopyBlitResolveImage
881 {
882 
883 class ImplementationBase : public Operation
884 {
885 public:
886 	//! Copy/Blit/Resolve etc. operation
887 	virtual void recordCopyCommand (const VkCommandBuffer cmdBuffer) = 0;
888 
889 	//! Get source stage mask that is used during read - added to test synchronization2 new stage masks
890 	virtual VkPipelineStageFlags2KHR getReadSrcStageMask() const = 0;
891 
ImplementationBase(OperationContext & context,Resource & resource,const AccessMode mode)892 	ImplementationBase (OperationContext& context, Resource& resource, const AccessMode mode)
893 		: m_context		(context)
894 		, m_resource	(resource)
895 		, m_mode		(mode)
896 		, m_bufferSize	(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
897 	{
898 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
899 		const VkDevice			device		= m_context.getDevice();
900 		Allocator&				allocator	= m_context.getAllocator();
901 
902 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
903 			vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
904 			MemoryRequirement::HostVisible));
905 
906 		const Allocation& alloc = m_hostBuffer->getAllocation();
907 		if (m_mode == ACCESS_MODE_READ)
908 			deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_bufferSize));
909 		else
910 			fillPattern(alloc.getHostPtr(), m_bufferSize);
911 		flushAlloc(vk, device, alloc);
912 
913 		// Staging image
914 		const auto& imgResource = m_resource.getImage();
915 		m_image = de::MovePtr<Image>(new Image(
916 			vk, device, allocator,
917 			makeImageCreateInfo(imgResource.imageType, imgResource.extent, imgResource.format,
918 								(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
919 			MemoryRequirement::Any));
920 	}
921 
recordCommands(const VkCommandBuffer cmdBuffer)922 	void recordCommands (const VkCommandBuffer cmdBuffer)
923 	{
924 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
925 		const VkBufferImageCopy		bufferCopyRegion		= makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
926 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
927 
928 		// Staging image layout
929 		{
930 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
931 				VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,		// VkPipelineStageFlags2KHR			srcStageMask
932 				(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
933 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
934 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
935 				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
936 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					newLayout
937 				**m_image,										// VkImage							image
938 				m_resource.getImage().subresourceRange			// VkImageSubresourceRange			subresourceRange
939 			);
940 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
941 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
942 		}
943 
944 		if (m_mode == ACCESS_MODE_READ)
945 		{
946 			// Resource Image -> Staging image
947 			recordCopyCommand(cmdBuffer);
948 
949 			// Staging image layout
950 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
951 				getReadSrcStageMask(),							// VkPipelineStageFlags2KHR			srcStageMask
952 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				srcAccessMask
953 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
954 				VK_ACCESS_2_TRANSFER_READ_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
955 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					oldLayout
956 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout					newLayout
957 				**m_image,										// VkImage							image
958 				m_resource.getImage().subresourceRange			// VkImageSubresourceRange			subresourceRange
959 			);
960 			VkDependencyInfoKHR imageDependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
961 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &imageDependencyInfo);
962 
963 			// Image -> Host buffer
964 			vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &bufferCopyRegion);
965 
966 			// Insert a barrier so copied data is available to the host
967 			const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
968 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			srcStageMask
969 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				srcAccessMask
970 				VK_PIPELINE_STAGE_2_HOST_BIT_KHR,				// VkPipelineStageFlags2KHR			dstStageMask
971 				VK_ACCESS_2_HOST_READ_BIT_KHR,					// VkAccessFlags2KHR				dstAccessMask
972 				**m_hostBuffer,									// VkBuffer							buffer
973 				0u,												// VkDeviceSize						offset
974 				m_bufferSize									// VkDeviceSize						size
975 			);
976 			VkDependencyInfoKHR bufferDependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
977 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &bufferDependencyInfo);
978 		}
979 		else
980 		{
981 			// Host buffer -> Staging image
982 			vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferCopyRegion);
983 
984 			// Staging image layout
985 			{
986 				const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
987 					VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			srcStageMask
988 					VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				srcAccessMask
989 					VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
990 					VK_ACCESS_2_TRANSFER_READ_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
991 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					oldLayout
992 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout					newLayout
993 					**m_image,										// VkImage							image
994 					m_resource.getImage().subresourceRange			// VkImageSubresourceRange			subresourceRange
995 				);
996 				VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
997 				synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
998 			}
999 
1000 			// Resource image layout
1001 			{
1002 				const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1003 					VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,		// VkPipelineStageFlags2KHR			srcStageMask
1004 					(VkAccessFlags2KHR)0,							// VkAccessFlags2KHR				srcAccessMask
1005 					VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
1006 					VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
1007 					VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
1008 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					newLayout
1009 					m_resource.getImage().handle,					// VkImage							image
1010 					m_resource.getImage().subresourceRange			// VkImageSubresourceRange			subresourceRange
1011 				);
1012 				VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1013 				synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1014 			}
1015 
1016 			// Staging image -> Resource Image
1017 			recordCopyCommand(cmdBuffer);
1018 		}
1019 	}
1020 
getInSyncInfo(void) const1021 	SyncInfo getInSyncInfo (void) const
1022 	{
1023 		const VkAccessFlags2KHR	access		= (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_TRANSFER_READ_BIT_KHR : VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
1024 		const VkImageLayout		layout		= (m_mode == ACCESS_MODE_READ ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
1025 		const SyncInfo			syncInfo	=
1026 		{
1027 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
1028 			access,									// VkAccessFlags			accessMask;
1029 			layout,									// VkImageLayout			imageLayout;
1030 		};
1031 		return syncInfo;
1032 	}
1033 
getOutSyncInfo(void) const1034 	SyncInfo getOutSyncInfo (void) const
1035 	{
1036 		const VkAccessFlags2KHR	access		= (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_TRANSFER_READ_BIT_KHR : VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
1037 		const VkImageLayout		layout		= (m_mode == ACCESS_MODE_READ ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
1038 		const SyncInfo			syncInfo	=
1039 		{
1040 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
1041 			access,									// VkAccessFlags			accessMask;
1042 			layout,									// VkImageLayout			imageLayout;
1043 		};
1044 		return syncInfo;
1045 	}
1046 
getData(void) const1047 	Data getData (void) const
1048 	{
1049 		return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
1050 	}
1051 
setData(const Data & data)1052 	void setData (const Data& data)
1053 	{
1054 		DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
1055 		setHostBufferData(m_context, *m_hostBuffer, data);
1056 	}
1057 
1058 protected:
1059 	OperationContext&		m_context;
1060 	Resource&				m_resource;
1061 	const AccessMode		m_mode;
1062 	const VkDeviceSize		m_bufferSize;
1063 	de::MovePtr<Buffer>		m_hostBuffer;
1064 	de::MovePtr<Image>		m_image;
1065 };
1066 
makeExtentOffset(const Resource & resource)1067 VkOffset3D makeExtentOffset (const Resource& resource)
1068 {
1069 	DE_ASSERT(resource.getType() == RESOURCE_TYPE_IMAGE);
1070 	const VkExtent3D extent = resource.getImage().extent;
1071 
1072 	switch (resource.getImage().imageType)
1073 	{
1074 		case VK_IMAGE_TYPE_1D:	return makeOffset3D(extent.width, 1, 1);
1075 		case VK_IMAGE_TYPE_2D:	return makeOffset3D(extent.width, extent.height, 1);
1076 		case VK_IMAGE_TYPE_3D:	return makeOffset3D(extent.width, extent.height, extent.depth);
1077 		default:
1078 			DE_ASSERT(0);
1079 			return VkOffset3D();
1080 	}
1081 }
1082 
makeBlitRegion(const Resource & resource)1083 VkImageBlit makeBlitRegion (const Resource& resource)
1084 {
1085 	const VkImageBlit blitRegion =
1086 	{
1087 		resource.getImage().subresourceLayers,					// VkImageSubresourceLayers    srcSubresource;
1088 		{ makeOffset3D(0, 0, 0), makeExtentOffset(resource) },	// VkOffset3D                  srcOffsets[2];
1089 		resource.getImage().subresourceLayers,					// VkImageSubresourceLayers    dstSubresource;
1090 		{ makeOffset3D(0, 0, 0), makeExtentOffset(resource) },	// VkOffset3D                  dstOffsets[2];
1091 	};
1092 	return blitRegion;
1093 }
1094 
1095 class BlitImplementation : public ImplementationBase
1096 {
1097 public:
BlitImplementation(OperationContext & context,Resource & resource,const AccessMode mode)1098 	BlitImplementation (OperationContext& context, Resource& resource, const AccessMode mode)
1099 		: ImplementationBase	(context, resource, mode)
1100 		, m_blitRegion			(makeBlitRegion(m_resource))
1101 	{
1102 		const InstanceInterface&	vki				= m_context.getInstanceInterface();
1103 		const VkPhysicalDevice		physDevice		= m_context.getPhysicalDevice();
1104 		const auto&					imgResource		= m_resource.getImage();
1105 		const VkFormatProperties	formatProps		= getPhysicalDeviceFormatProperties(vki, physDevice, imgResource.format);
1106 		const auto&					features		= ((imgResource.tiling == VK_IMAGE_TILING_LINEAR) ? formatProps.linearTilingFeatures : formatProps.optimalTilingFeatures);
1107 		const VkFormatFeatureFlags	requiredFlags	= (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT);
1108 
1109 		// SRC and DST blit is required because both images are using the same format.
1110 		if ((features & requiredFlags) != requiredFlags)
1111 			TCU_THROW(NotSupportedError, "Format doesn't support blits");
1112 	}
1113 
recordCopyCommand(const VkCommandBuffer cmdBuffer)1114 	void recordCopyCommand (const VkCommandBuffer cmdBuffer)
1115 	{
1116 		const DeviceInterface&	vk	= m_context.getDeviceInterface();
1117 
1118 		if (m_mode == ACCESS_MODE_READ)
1119 		{
1120 			// Resource Image -> Staging image
1121 			vk.cmdBlitImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1122 				1u, &m_blitRegion, VK_FILTER_NEAREST);
1123 		}
1124 		else
1125 		{
1126 			// Staging image -> Resource Image
1127 			vk.cmdBlitImage(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1128 				1u, &m_blitRegion, VK_FILTER_NEAREST);
1129 		}
1130 	}
1131 
getReadSrcStageMask() const1132 	VkPipelineStageFlags2KHR getReadSrcStageMask() const
1133 	{
1134 		return (m_context.getSynchronizationType() == SynchronizationType::LEGACY) ? VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR : VK_PIPELINE_STAGE_2_BLIT_BIT_KHR;
1135 	}
1136 
1137 
1138 private:
1139 	const VkImageBlit	m_blitRegion;
1140 };
1141 
1142 template <typename ImageCopyOrResolve>
makeImageRegion(const Resource & resource)1143 ImageCopyOrResolve makeImageRegion (const Resource& resource)
1144 {
1145 	return
1146 	{
1147 		resource.getImage().subresourceLayers,		// VkImageSubresourceLayers    srcSubresource;
1148 		makeOffset3D(0, 0, 0),						// VkOffset3D                  srcOffset;
1149 		resource.getImage().subresourceLayers,		// VkImageSubresourceLayers    dstSubresource;
1150 		makeOffset3D(0, 0, 0),						// VkOffset3D                  dstOffset;
1151 		resource.getImage().extent,					// VkExtent3D                  extent;
1152 	};
1153 }
1154 
1155 class CopyImplementation : public ImplementationBase
1156 {
1157 public:
CopyImplementation(OperationContext & context,Resource & resource,const AccessMode mode)1158 	CopyImplementation (OperationContext& context, Resource& resource, const AccessMode mode)
1159 		: ImplementationBase	(context, resource, mode)
1160 		, m_imageCopyRegion		(makeImageRegion<VkImageCopy>(m_resource))
1161 	{
1162 	}
1163 
recordCopyCommand(const VkCommandBuffer cmdBuffer)1164 	void recordCopyCommand (const VkCommandBuffer cmdBuffer)
1165 	{
1166 		const DeviceInterface&	vk	= m_context.getDeviceInterface();
1167 
1168 		if (m_mode == ACCESS_MODE_READ)
1169 		{
1170 			// Resource Image -> Staging image
1171 			vk.cmdCopyImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageCopyRegion);
1172 		}
1173 		else
1174 		{
1175 			// Staging image -> Resource Image
1176 			vk.cmdCopyImage(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageCopyRegion);
1177 		}
1178 	}
1179 
getReadSrcStageMask() const1180 	VkPipelineStageFlags2KHR getReadSrcStageMask() const
1181 	{
1182 		return (m_context.getSynchronizationType() == SynchronizationType::LEGACY) ? VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR : VK_PIPELINE_STAGE_2_COPY_BIT_KHR;
1183 	}
1184 
1185 private:
1186 	const VkImageCopy	m_imageCopyRegion;
1187 };
1188 
1189 class ResolveImplementation : public ImplementationBase
1190 {
1191 public:
ResolveImplementation(OperationContext & context,Resource & resource,const AccessMode mode)1192 	ResolveImplementation(OperationContext& context, Resource& resource, const AccessMode mode)
1193 		: ImplementationBase	(context, resource, mode)
1194 		, m_imageResolveRegion	(makeImageRegion<VkImageResolve>(resource))
1195 	{
1196 		DE_ASSERT(m_mode == ACCESS_MODE_READ);
1197 	}
1198 
recordCopyCommand(const VkCommandBuffer cmdBuffer)1199 	void recordCopyCommand(const VkCommandBuffer cmdBuffer)
1200 	{
1201 		const DeviceInterface&	vk = m_context.getDeviceInterface();
1202 
1203 		// Resource Image -> Staging image
1204 		vk.cmdResolveImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageResolveRegion);
1205 	}
1206 
getReadSrcStageMask() const1207 	VkPipelineStageFlags2KHR getReadSrcStageMask() const
1208 	{
1209 		return (m_context.getSynchronizationType() == SynchronizationType::LEGACY) ? VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR : VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR;
1210 	}
1211 
1212 private:
1213 	VkImageResolve m_imageResolveRegion;
1214 };
1215 
1216 enum Type
1217 {
1218 	TYPE_COPY,
1219 	TYPE_BLIT,
1220 	TYPE_RESOLVE,
1221 };
1222 
1223 class Support : public OperationSupport
1224 {
1225 public:
Support(const ResourceDescription & resourceDesc,const Type type,const AccessMode mode)1226 	Support (const ResourceDescription& resourceDesc, const Type type, const AccessMode mode)
1227 		: m_type				(type)
1228 		, m_mode				(mode)
1229 	{
1230 		DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_IMAGE);
1231 
1232 		const bool isDepthStencil	= isDepthStencilFormat(resourceDesc.imageFormat);
1233 		m_requiredQueueFlags		= (isDepthStencil || m_type != TYPE_COPY ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT);
1234 
1235 		// Don't blit depth/stencil images.
1236 		DE_ASSERT(m_type != TYPE_BLIT || !isDepthStencil);
1237 	}
1238 
getInResourceUsageFlags(void) const1239 	deUint32 getInResourceUsageFlags (void) const
1240 	{
1241 		return (m_mode == ACCESS_MODE_READ ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : 0);
1242 	}
1243 
getOutResourceUsageFlags(void) const1244 	deUint32 getOutResourceUsageFlags (void) const
1245 	{
1246 		return (m_mode == ACCESS_MODE_WRITE ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0);
1247 	}
1248 
getQueueFlags(const OperationContext & context) const1249 	VkQueueFlags getQueueFlags (const OperationContext& context) const
1250 	{
1251 		DE_UNREF(context);
1252 		return m_requiredQueueFlags;
1253 	}
1254 
build(OperationContext & context,Resource & resource) const1255 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
1256 	{
1257 		if (m_type == TYPE_COPY)
1258 			return de::MovePtr<Operation>(new CopyImplementation(context, resource, m_mode));
1259 		else if (m_type == TYPE_BLIT)
1260 			return de::MovePtr<Operation>(new BlitImplementation(context, resource, m_mode));
1261 		else
1262 			return de::MovePtr<Operation>(new ResolveImplementation(context, resource, m_mode));
1263 	}
1264 
build(OperationContext &,Resource &,Resource &) const1265 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
1266 	{
1267 		DE_ASSERT(0);
1268 		return de::MovePtr<Operation>();
1269 	}
1270 
1271 private:
1272 	const Type			m_type;
1273 	const AccessMode	m_mode;
1274 	VkQueueFlags		m_requiredQueueFlags;
1275 };
1276 
1277 class BlitCopyImplementation : public Operation
1278 {
1279 public:
BlitCopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)1280 	BlitCopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
1281 		: m_context			(context)
1282 		, m_inResource		(inResource)
1283 		, m_outResource		(outResource)
1284 		, m_blitRegion		(makeBlitRegion(m_inResource))
1285 	{
1286 		DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_IMAGE);
1287 		DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_IMAGE);
1288 
1289 		const InstanceInterface&	vki				= m_context.getInstanceInterface();
1290 		const VkPhysicalDevice		physDevice		= m_context.getPhysicalDevice();
1291 		const auto&					imgResource		= m_inResource.getImage();
1292 		const VkFormatProperties	formatProps		= getPhysicalDeviceFormatProperties(vki, physDevice, imgResource.format);
1293 		const auto&					features		= ((imgResource.tiling == VK_IMAGE_TILING_LINEAR) ? formatProps.linearTilingFeatures : formatProps.optimalTilingFeatures);
1294 		const VkFormatFeatureFlags	requiredFlags	= (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT);
1295 
1296 		// SRC and DST blit is required because both images are using the same format.
1297 		if ((features & requiredFlags) != requiredFlags)
1298 			TCU_THROW(NotSupportedError, "Format doesn't support blits");
1299 	}
1300 
recordCommands(const VkCommandBuffer cmdBuffer)1301 	void recordCommands (const VkCommandBuffer cmdBuffer)
1302 	{
1303 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
1304 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1305 
1306 		{
1307 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1308 				VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags2KHR			srcStageMask
1309 				(VkAccessFlags2KHR)0,							// VkAccessFlags2KHR				srcAccessMask
1310 				VK_PIPELINE_STAGE_TRANSFER_BIT,					// VkPipelineStageFlags2KHR			dstStageMask
1311 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
1312 				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
1313 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					newLayout
1314 				m_outResource.getImage().handle,				// VkImage							image
1315 				m_outResource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
1316 			);
1317 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1318 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1319 		}
1320 
1321 		vk.cmdBlitImage(cmdBuffer,
1322 						m_inResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1323 						m_outResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1324 						1u, &m_blitRegion, VK_FILTER_NEAREST);
1325 	}
1326 
getInSyncInfo(void) const1327 	SyncInfo getInSyncInfo (void) const
1328 	{
1329 		const SyncInfo		syncInfo	=
1330 		{
1331 			VK_PIPELINE_STAGE_TRANSFER_BIT,			// VkPipelineStageFlags		stageMask;
1332 			VK_ACCESS_2_TRANSFER_READ_BIT_KHR,		// VkAccessFlags			accessMask;
1333 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,	// VkImageLayout			imageLayout;
1334 		};
1335 		return syncInfo;
1336 	}
1337 
getOutSyncInfo(void) const1338 	SyncInfo getOutSyncInfo (void) const
1339 	{
1340 		const SyncInfo		syncInfo	=
1341 		{
1342 			VK_PIPELINE_STAGE_TRANSFER_BIT,			// VkPipelineStageFlags		stageMask;
1343 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,		// VkAccessFlags			accessMask;
1344 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			imageLayout;
1345 		};
1346 		return syncInfo;
1347 	}
1348 
getData(void) const1349 	Data getData (void) const
1350 	{
1351 		Data data = { 0, DE_NULL };
1352 		return data;
1353 	}
1354 
setData(const Data &)1355 	void setData (const Data&)
1356 	{
1357 		DE_ASSERT(0);
1358 	}
1359 
1360 private:
1361 	OperationContext&	m_context;
1362 	Resource&			m_inResource;
1363 	Resource&			m_outResource;
1364 	const VkImageBlit	m_blitRegion;
1365 };
1366 
1367 class CopyCopyImplementation : public Operation
1368 {
1369 public:
CopyCopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)1370 	CopyCopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
1371 		: m_context			(context)
1372 		, m_inResource		(inResource)
1373 		, m_outResource		(outResource)
1374 		, m_imageCopyRegion	(makeImageRegion<VkImageCopy>(m_inResource))
1375 	{
1376 		DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_IMAGE);
1377 		DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_IMAGE);
1378 	}
1379 
recordCommands(const VkCommandBuffer cmdBuffer)1380 	void recordCommands (const VkCommandBuffer cmdBuffer)
1381 	{
1382 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
1383 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1384 
1385 		{
1386 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1387 				VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags2KHR			srcStageMask
1388 				(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
1389 				VK_PIPELINE_STAGE_TRANSFER_BIT,					// VkPipelineStageFlags2KHR			dstStageMask
1390 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
1391 				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
1392 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					newLayout
1393 				m_outResource.getImage().handle,				// VkImage							image
1394 				m_outResource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
1395 			);
1396 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1397 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1398 		}
1399 
1400 		vk.cmdCopyImage(cmdBuffer,
1401 						m_inResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1402 						m_outResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1403 						1u, &m_imageCopyRegion);
1404 	}
1405 
getInSyncInfo(void) const1406 	SyncInfo getInSyncInfo (void) const
1407 	{
1408 		const SyncInfo		syncInfo	=
1409 		{
1410 			VK_PIPELINE_STAGE_TRANSFER_BIT,			// VkPipelineStageFlags		stageMask;
1411 			VK_ACCESS_2_TRANSFER_READ_BIT_KHR,		// VkAccessFlags			accessMask;
1412 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,	// VkImageLayout			imageLayout;
1413 		};
1414 		return syncInfo;
1415 	}
1416 
getOutSyncInfo(void) const1417 	SyncInfo getOutSyncInfo (void) const
1418 	{
1419 		const SyncInfo		syncInfo	=
1420 		{
1421 			VK_PIPELINE_STAGE_TRANSFER_BIT,			// VkPipelineStageFlags		stageMask;
1422 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,		// VkAccessFlags			accessMask;
1423 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			imageLayout;
1424 		};
1425 		return syncInfo;
1426 	}
1427 
getData(void) const1428 	Data getData (void) const
1429 	{
1430 		Data data = { 0, DE_NULL };
1431 		return data;
1432 	}
1433 
setData(const Data &)1434 	void setData (const Data&)
1435 	{
1436 		DE_ASSERT(0);
1437 	}
1438 
1439 private:
1440 	OperationContext&	m_context;
1441 	Resource&			m_inResource;
1442 	Resource&			m_outResource;
1443 	const VkImageCopy	m_imageCopyRegion;
1444 };
1445 
1446 class CopySupport : public OperationSupport
1447 {
1448 public:
CopySupport(const ResourceDescription & resourceDesc,const Type type)1449 	CopySupport (const ResourceDescription& resourceDesc, const Type type)
1450 		: m_type				(type)
1451 	{
1452 		DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_IMAGE);
1453 
1454 		const bool isDepthStencil	= isDepthStencilFormat(resourceDesc.imageFormat);
1455 		m_requiredQueueFlags		= (isDepthStencil || m_type == TYPE_BLIT ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT);
1456 
1457 		// Don't blit depth/stencil images.
1458 		DE_ASSERT(m_type != TYPE_BLIT || !isDepthStencil);
1459 	}
1460 
getInResourceUsageFlags(void) const1461 	deUint32 getInResourceUsageFlags (void) const
1462 	{
1463 		return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1464 	}
1465 
getOutResourceUsageFlags(void) const1466 	deUint32 getOutResourceUsageFlags (void) const
1467 	{
1468 		return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1469 	}
1470 
getQueueFlags(const OperationContext & context) const1471 	VkQueueFlags getQueueFlags (const OperationContext& context) const
1472 	{
1473 		DE_UNREF(context);
1474 		return m_requiredQueueFlags;
1475 	}
1476 
build(OperationContext &,Resource &) const1477 	de::MovePtr<Operation> build (OperationContext&, Resource&) const
1478 	{
1479 		DE_ASSERT(0);
1480 		return de::MovePtr<Operation>();
1481 	}
1482 
build(OperationContext & context,Resource & inResource,Resource & outResource) const1483 	de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
1484 	{
1485 		if (m_type == TYPE_COPY)
1486 			return de::MovePtr<Operation>(new CopyCopyImplementation(context, inResource, outResource));
1487 		else
1488 			return de::MovePtr<Operation>(new BlitCopyImplementation(context, inResource, outResource));
1489 	}
1490 
1491 private:
1492 	const Type			m_type;
1493 	VkQueueFlags		m_requiredQueueFlags;
1494 };
1495 
1496 } // CopyBlitImage ns
1497 
1498 namespace ShaderAccess
1499 {
1500 
1501 enum DispatchCall
1502 {
1503 	DISPATCH_CALL_DISPATCH,
1504 	DISPATCH_CALL_DISPATCH_INDIRECT,
1505 };
1506 
1507 class GraphicsPipeline : public Pipeline
1508 {
1509 public:
GraphicsPipeline(OperationContext & context,const VkShaderStageFlagBits stage,const std::string & shaderPrefix,const VkDescriptorSetLayout descriptorSetLayout)1510 	GraphicsPipeline (OperationContext& context, const VkShaderStageFlagBits stage, const std::string& shaderPrefix, const VkDescriptorSetLayout descriptorSetLayout)
1511 		: m_vertices	(context)
1512 	{
1513 		const DeviceInterface&		vk				= context.getDeviceInterface();
1514 		const VkDevice				device			= context.getDevice();
1515 		Allocator&					allocator		= context.getAllocator();
1516 		const VkShaderStageFlags	requiredStages	= getRequiredStages(stage);
1517 
1518 		// Color attachment
1519 
1520 		m_colorFormat					= VK_FORMAT_R8G8B8A8_UNORM;
1521 		m_colorImageSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1522 		m_colorImageExtent				= makeExtent3D(16u, 16u, 1u);
1523 		m_colorAttachmentImage			= de::MovePtr<Image>(new Image(vk, device, allocator,
1524 			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
1525 								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
1526 			MemoryRequirement::Any));
1527 
1528 		// Pipeline
1529 
1530 		m_colorAttachmentView	= makeImageView		(vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
1531 		m_renderPass			= makeRenderPass	(vk, device, m_colorFormat);
1532 		m_framebuffer			= makeFramebuffer	(vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height);
1533 		m_pipelineLayout		= makePipelineLayout(vk, device, descriptorSetLayout);
1534 
1535 		GraphicsPipelineBuilder pipelineBuilder;
1536 		pipelineBuilder
1537 			.setRenderSize					(tcu::IVec2(m_colorImageExtent.width, m_colorImageExtent.height))
1538 			.setVertexInputSingleAttribute	(m_vertices.getVertexFormat(), m_vertices.getVertexStride())
1539 			.setShader						(vk, device, VK_SHADER_STAGE_VERTEX_BIT,	context.getBinaryCollection().get(shaderPrefix + "vert"), DE_NULL)
1540 			.setShader						(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,	context.getBinaryCollection().get(shaderPrefix + "frag"), DE_NULL);
1541 
1542 		if (requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
1543 			pipelineBuilder
1544 				.setPatchControlPoints	(m_vertices.getNumVertices())
1545 				.setShader				(vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		context.getBinaryCollection().get(shaderPrefix + "tesc"), DE_NULL)
1546 				.setShader				(vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,	context.getBinaryCollection().get(shaderPrefix + "tese"), DE_NULL);
1547 
1548 		if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
1549 			pipelineBuilder
1550 				.setShader	(vk, device, VK_SHADER_STAGE_GEOMETRY_BIT,	context.getBinaryCollection().get(shaderPrefix + "geom"), DE_NULL);
1551 
1552 		m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData(), context.getResourceInterface());
1553 	}
1554 
recordCommands(OperationContext & context,const VkCommandBuffer cmdBuffer,const VkDescriptorSet descriptorSet)1555 	void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
1556 	{
1557 		const DeviceInterface&		vk						= context.getDeviceInterface();
1558 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(context.getSynchronizationType(), vk, DE_FALSE);
1559 
1560 		// Change color attachment image layout
1561 		{
1562 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1563 				VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags2KHR			srcStageMask
1564 				(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
1565 				VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// VkPipelineStageFlags2KHR			dstStageMask
1566 				VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,		// VkAccessFlags2KHR				dstAccessMask
1567 				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
1568 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout					newLayout
1569 				**m_colorAttachmentImage,						// VkImage							image
1570 				m_colorImageSubresourceRange					// VkImageSubresourceRange			subresourceRange
1571 			);
1572 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1573 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1574 		}
1575 
1576 		{
1577 			const VkRect2D	renderArea	= makeRect2D(m_colorImageExtent);
1578 			const tcu::Vec4	clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1579 
1580 			beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
1581 		}
1582 
1583 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1584 		vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1585 		{
1586 			const VkDeviceSize	vertexBufferOffset	= 0ull;
1587 			const VkBuffer		vertexBuffer		= m_vertices.getVertexBuffer();
1588 			vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
1589 		}
1590 
1591 		vk.cmdDraw(cmdBuffer, m_vertices.getNumVertices(), 1u, 0u, 0u);
1592 		endRenderPass(vk, cmdBuffer);
1593 	}
1594 
1595 private:
1596 	const VertexGrid			m_vertices;
1597 	VkFormat					m_colorFormat;
1598 	de::MovePtr<Image>			m_colorAttachmentImage;
1599 	Move<VkImageView>			m_colorAttachmentView;
1600 	VkExtent3D					m_colorImageExtent;
1601 	VkImageSubresourceRange		m_colorImageSubresourceRange;
1602 	Move<VkRenderPass>			m_renderPass;
1603 	Move<VkFramebuffer>			m_framebuffer;
1604 	Move<VkPipelineLayout>		m_pipelineLayout;
1605 	Move<VkPipeline>			m_pipeline;
1606 };
1607 
1608 class ComputePipeline : public Pipeline
1609 {
1610 public:
ComputePipeline(OperationContext & context,const DispatchCall dispatchCall,const std::string & shaderPrefix,const VkDescriptorSetLayout descriptorSetLayout)1611 	ComputePipeline (OperationContext& context, const DispatchCall dispatchCall, const std::string& shaderPrefix, const VkDescriptorSetLayout descriptorSetLayout)
1612 		: m_dispatchCall	(dispatchCall)
1613 	{
1614 		const DeviceInterface&	vk			= context.getDeviceInterface();
1615 		const VkDevice			device		= context.getDevice();
1616 		Allocator&				allocator	= context.getAllocator();
1617 
1618 		if (m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT)
1619 		{
1620 			m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
1621 				makeBufferCreateInfo(sizeof(VkDispatchIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
1622 
1623 			const Allocation&					alloc				= m_indirectBuffer->getAllocation();
1624 			VkDispatchIndirectCommand* const	pIndirectCommand	= static_cast<VkDispatchIndirectCommand*>(alloc.getHostPtr());
1625 
1626 			pIndirectCommand->x	= 1u;
1627 			pIndirectCommand->y = 1u;
1628 			pIndirectCommand->z	= 1u;
1629 
1630 			flushAlloc(vk, device, alloc);
1631 		}
1632 
1633 		const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get(shaderPrefix + "comp"), (VkShaderModuleCreateFlags)0));
1634 
1635 		m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
1636 		m_pipeline		 = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData(), context.getResourceInterface());
1637 	}
1638 
recordCommands(OperationContext & context,const VkCommandBuffer cmdBuffer,const VkDescriptorSet descriptorSet)1639 	void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
1640 	{
1641 		const DeviceInterface&	vk	= context.getDeviceInterface();
1642 
1643 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
1644 		vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1645 
1646 		if (m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT)
1647 			vk.cmdDispatchIndirect(cmdBuffer, **m_indirectBuffer, 0u);
1648 		else
1649 			vk.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
1650 	}
1651 
1652 private:
1653 	const DispatchCall			m_dispatchCall;
1654 	de::MovePtr<Buffer>			m_indirectBuffer;
1655 	Move<VkPipelineLayout>		m_pipelineLayout;
1656 	Move<VkPipeline>			m_pipeline;
1657 };
1658 
1659 //! Read/write operation on a UBO/SSBO in graphics/compute pipeline.
1660 class BufferImplementation : public Operation
1661 {
1662 public:
BufferImplementation(OperationContext & context,Resource & resource,const VkShaderStageFlagBits stage,const BufferType bufferType,const std::string & shaderPrefix,const AccessMode mode,const PipelineType pipelineType,const DispatchCall dispatchCall)1663 	BufferImplementation (OperationContext&				context,
1664 						  Resource&						resource,
1665 						  const VkShaderStageFlagBits	stage,
1666 						  const BufferType				bufferType,
1667 						  const std::string&			shaderPrefix,
1668 						  const AccessMode				mode,
1669 						  const PipelineType			pipelineType,
1670 						  const DispatchCall			dispatchCall)
1671 		: m_context			(context)
1672 		, m_resource		(resource)
1673 		, m_stage			(stage)
1674 		, m_pipelineStage	(pipelineStageFlagsFromShaderStageFlagBits(m_stage))
1675 		, m_bufferType		(bufferType)
1676 		, m_mode			(mode)
1677 		, m_dispatchCall	(dispatchCall)
1678 	{
1679 		requireFeaturesForSSBOAccess (m_context, m_stage);
1680 
1681 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
1682 		const VkDevice			device		= m_context.getDevice();
1683 		Allocator&				allocator	= m_context.getAllocator();
1684 
1685 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1686 			vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
1687 
1688 		// Init host buffer data
1689 		{
1690 			const Allocation& alloc = m_hostBuffer->getAllocation();
1691 			if (m_mode == ACCESS_MODE_READ)
1692 				deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_resource.getBuffer().size));
1693 			else
1694 				fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
1695 			flushAlloc(vk, device, alloc);
1696 		}
1697 
1698 		// Prepare descriptors
1699 		{
1700 			const VkDescriptorType	bufferDescriptorType	= (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1701 
1702 			m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1703 				.addSingleBinding(bufferDescriptorType, m_stage)
1704 				.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
1705 				.build(vk, device);
1706 
1707 			m_descriptorPool = DescriptorPoolBuilder()
1708 				.addType(bufferDescriptorType)
1709 				.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1710 				.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1711 
1712 			m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1713 
1714 			const VkDescriptorBufferInfo  bufferInfo	 = makeDescriptorBufferInfo(m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size);
1715 			const VkDescriptorBufferInfo  hostBufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_resource.getBuffer().size);
1716 
1717 			if (m_mode == ACCESS_MODE_READ)
1718 			{
1719 				DescriptorSetUpdateBuilder()
1720 					.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), bufferDescriptorType, &bufferInfo)
1721 					.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
1722 					.update(vk, device);
1723 			}
1724 			else
1725 			{
1726 				DescriptorSetUpdateBuilder()
1727 					.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
1728 					.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
1729 					.update(vk, device);
1730 			}
1731 		}
1732 
1733 		// Create pipeline
1734 		m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
1735 															 : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
1736 	}
1737 
recordCommands(const VkCommandBuffer cmdBuffer)1738 	void recordCommands (const VkCommandBuffer cmdBuffer)
1739 	{
1740 		m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
1741 
1742 		// Post draw/dispatch commands
1743 
1744 		if (m_mode == ACCESS_MODE_READ)
1745 		{
1746 			const DeviceInterface&		vk						= m_context.getDeviceInterface();
1747 			SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1748 
1749 			// Insert a barrier so data written by the shader is available to the host
1750 			const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
1751 				m_pipelineStage,							// VkPipelineStageFlags2KHR			srcStageMask
1752 				VK_ACCESS_2_SHADER_WRITE_BIT_KHR,			// VkAccessFlags2KHR				srcAccessMask
1753 				VK_PIPELINE_STAGE_HOST_BIT,					// VkPipelineStageFlags2KHR			dstStageMask
1754 				VK_ACCESS_2_HOST_READ_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
1755 				**m_hostBuffer,								// VkBuffer							buffer
1756 				0u,											// VkDeviceSize						offset
1757 				m_resource.getBuffer().size					// VkDeviceSize						size
1758 			);
1759 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
1760 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1761 		}
1762 	}
1763 
getInSyncInfo(void) const1764 	SyncInfo getInSyncInfo (void) const
1765 	{
1766 		const VkAccessFlags2KHR	accessFlags = (m_mode == ACCESS_MODE_READ ? (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_ACCESS_2_UNIFORM_READ_BIT_KHR
1767 																											 : VK_ACCESS_2_SHADER_READ_BIT_KHR)
1768 																	  : VK_ACCESS_2_SHADER_WRITE_BIT_KHR);
1769 		const SyncInfo			syncInfo	=
1770 		{
1771 			m_pipelineStage,				// VkPipelineStageFlags		stageMask;
1772 			accessFlags,					// VkAccessFlags			accessMask;
1773 			VK_IMAGE_LAYOUT_UNDEFINED,		// VkImageLayout			imageLayout;
1774 		};
1775 		return syncInfo;
1776 	}
1777 
getOutSyncInfo(void) const1778 	SyncInfo getOutSyncInfo (void) const
1779 	{
1780 		const VkAccessFlags	accessFlags = m_mode == ACCESS_MODE_WRITE ? VK_ACCESS_2_SHADER_WRITE_BIT_KHR : 0;
1781 		const SyncInfo		syncInfo	=
1782 		{
1783 			m_pipelineStage,				// VkPipelineStageFlags		stageMask;
1784 			accessFlags,					// VkAccessFlags			accessMask;
1785 			VK_IMAGE_LAYOUT_UNDEFINED,		// VkImageLayout			imageLayout;
1786 		};
1787 		return syncInfo;
1788 	}
1789 
getData(void) const1790 	Data getData (void) const
1791 	{
1792 		return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
1793 	}
1794 
setData(const Data & data)1795 	void setData (const Data& data)
1796 	{
1797 		DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
1798 		setHostBufferData(m_context, *m_hostBuffer, data);
1799 	}
1800 
1801 private:
1802 	OperationContext&			m_context;
1803 	Resource&					m_resource;
1804 	const VkShaderStageFlagBits	m_stage;
1805 	const VkPipelineStageFlags	m_pipelineStage;
1806 	const BufferType			m_bufferType;
1807 	const AccessMode			m_mode;
1808 	const DispatchCall			m_dispatchCall;
1809 	de::MovePtr<Buffer>			m_hostBuffer;
1810 	Move<VkDescriptorPool>		m_descriptorPool;
1811 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
1812 	Move<VkDescriptorSet>		m_descriptorSet;
1813 	de::MovePtr<Pipeline>		m_pipeline;
1814 };
1815 
1816 class ImageImplementation : public Operation
1817 {
1818 public:
ImageImplementation(OperationContext & context,Resource & resource,const VkShaderStageFlagBits stage,const std::string & shaderPrefix,const AccessMode mode,const PipelineType pipelineType,const DispatchCall dispatchCall)1819 	ImageImplementation (OperationContext&				context,
1820 						 Resource&						resource,
1821 						 const VkShaderStageFlagBits	stage,
1822 						 const std::string&				shaderPrefix,
1823 						 const AccessMode				mode,
1824 						 const PipelineType				pipelineType,
1825 						 const DispatchCall				dispatchCall)
1826 		: m_context				(context)
1827 		, m_resource			(resource)
1828 		, m_stage				(stage)
1829 		, m_pipelineStage		(pipelineStageFlagsFromShaderStageFlagBits(m_stage))
1830 		, m_mode				(mode)
1831 		, m_dispatchCall		(dispatchCall)
1832 		, m_hostBufferSizeBytes	(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
1833 	{
1834 		const DeviceInterface&		vk			= m_context.getDeviceInterface();
1835 		const InstanceInterface&	vki			= m_context.getInstanceInterface();
1836 		const VkDevice				device		= m_context.getDevice();
1837 		const VkPhysicalDevice		physDevice	= m_context.getPhysicalDevice();
1838 		Allocator&					allocator	= m_context.getAllocator();
1839 
1840 		// Image stores are always required, in either access mode.
1841 		requireFeaturesForSSBOAccess(m_context, m_stage);
1842 
1843 		// Some storage image formats may not be supported
1844 		const auto& imgResource = m_resource.getImage();
1845 		requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
1846 
1847 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1848 			vk, device, allocator, makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
1849 			MemoryRequirement::HostVisible));
1850 
1851 		// Init host buffer data
1852 		{
1853 			const Allocation& alloc = m_hostBuffer->getAllocation();
1854 			if (m_mode == ACCESS_MODE_READ)
1855 				deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_hostBufferSizeBytes));
1856 			else
1857 				fillPattern(alloc.getHostPtr(), m_hostBufferSizeBytes);
1858 			flushAlloc(vk, device, alloc);
1859 		}
1860 
1861 		// Image resources
1862 		{
1863 			m_image = de::MovePtr<Image>(new Image(vk, device, allocator,
1864 				makeImageCreateInfo(m_resource.getImage().imageType, m_resource.getImage().extent, m_resource.getImage().format,
1865 									(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT),
1866 									VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
1867 				MemoryRequirement::Any));
1868 
1869 			if (m_mode == ACCESS_MODE_READ)
1870 			{
1871 				m_srcImage = &m_resource.getImage().handle;
1872 				m_dstImage = &(**m_image);
1873 			}
1874 			else
1875 			{
1876 				m_srcImage = &(**m_image);
1877 				m_dstImage = &m_resource.getImage().handle;
1878 			}
1879 
1880 			const VkImageViewType viewType = getImageViewType(m_resource.getImage().imageType);
1881 
1882 			m_srcImageView	= makeImageView(vk, device, *m_srcImage, viewType, m_resource.getImage().format, m_resource.getImage().subresourceRange);
1883 			m_dstImageView	= makeImageView(vk, device, *m_dstImage, viewType, m_resource.getImage().format, m_resource.getImage().subresourceRange);
1884 		}
1885 
1886 		// Prepare descriptors
1887 		{
1888 			m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1889 				.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
1890 				.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
1891 				.build(vk, device);
1892 
1893 			m_descriptorPool = DescriptorPoolBuilder()
1894 				.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1895 				.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1896 				.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1897 
1898 			m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1899 
1900 			const VkDescriptorImageInfo srcImageInfo = makeDescriptorImageInfo(DE_NULL, *m_srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1901 			const VkDescriptorImageInfo dstImageInfo = makeDescriptorImageInfo(DE_NULL, *m_dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1902 
1903 			DescriptorSetUpdateBuilder()
1904 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &srcImageInfo)
1905 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &dstImageInfo)
1906 				.update(vk, device);
1907 		}
1908 
1909 		// Create pipeline
1910 		m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
1911 															 : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
1912 	}
1913 
recordCommands(const VkCommandBuffer cmdBuffer)1914 	void recordCommands (const VkCommandBuffer cmdBuffer)
1915 	{
1916 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
1917 		const VkBufferImageCopy		bufferCopyRegion		= makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
1918 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1919 
1920 		// Destination image layout
1921 		{
1922 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1923 				VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,			// VkPipelineStageFlags2KHR			srcStageMask
1924 				(VkAccessFlags)0,							// VkAccessFlags2KHR				srcAccessMask
1925 				m_pipelineStage,							// VkPipelineStageFlags2KHR			dstStageMask
1926 				VK_ACCESS_2_SHADER_WRITE_BIT_KHR,			// VkAccessFlags2KHR				dstAccessMask
1927 				VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					oldLayout
1928 				VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					newLayout
1929 				*m_dstImage,								// VkImage							image
1930 				m_resource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
1931 			);
1932 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1933 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1934 		}
1935 
1936 		// In write mode, source image must be filled with data.
1937 		if (m_mode == ACCESS_MODE_WRITE)
1938 		{
1939 			// Layout for transfer
1940 			{
1941 				const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1942 					VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,			// VkPipelineStageFlags2KHR			srcStageMask
1943 					(VkAccessFlags)0,							// VkAccessFlags2KHR				srcAccessMask
1944 					VK_PIPELINE_STAGE_TRANSFER_BIT,				// VkPipelineStageFlags2KHR			dstStageMask
1945 					VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,			// VkAccessFlags2KHR				dstAccessMask
1946 					VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					oldLayout
1947 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout					newLayout
1948 					*m_srcImage,								// VkImage							image
1949 					m_resource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
1950 				);
1951 				VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1952 				synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1953 			}
1954 
1955 			// Host buffer -> Src image
1956 			vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, *m_srcImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferCopyRegion);
1957 
1958 			// Layout for shader reading
1959 			{
1960 				const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1961 					VK_PIPELINE_STAGE_TRANSFER_BIT,				// VkPipelineStageFlags2KHR			srcStageMask
1962 					VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,			// VkAccessFlags2KHR				srcAccessMask
1963 					m_pipelineStage,							// VkPipelineStageFlags2KHR			dstStageMask
1964 					VK_ACCESS_2_SHADER_READ_BIT_KHR,			// VkAccessFlags2KHR				dstAccessMask
1965 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout					oldLayout
1966 					VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					newLayout
1967 					*m_srcImage,								// VkImage							image
1968 					m_resource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
1969 				);
1970 				VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1971 				synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1972 			}
1973 		}
1974 
1975 		// Execute shaders
1976 
1977 		m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
1978 
1979 		// Post draw/dispatch commands
1980 
1981 		if (m_mode == ACCESS_MODE_READ)
1982 		{
1983 			// Layout for transfer
1984 			{
1985 				const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1986 					m_pipelineStage,							// VkPipelineStageFlags2KHR			srcStageMask
1987 					VK_ACCESS_2_SHADER_WRITE_BIT_KHR,			// VkAccessFlags2KHR				srcAccessMask
1988 					VK_PIPELINE_STAGE_TRANSFER_BIT,				// VkPipelineStageFlags2KHR			dstStageMask
1989 					VK_ACCESS_2_TRANSFER_READ_BIT_KHR,			// VkAccessFlags2KHR				dstAccessMask
1990 					VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					oldLayout
1991 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout					newLayout
1992 					*m_dstImage,								// VkImage							image
1993 					m_resource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
1994 				);
1995 				VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1996 				synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1997 			}
1998 
1999 			// Dst image -> Host buffer
2000 			vk.cmdCopyImageToBuffer(cmdBuffer, *m_dstImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &bufferCopyRegion);
2001 
2002 			// Insert a barrier so data written by the shader is available to the host
2003 			{
2004 				const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
2005 					VK_PIPELINE_STAGE_TRANSFER_BIT,				// VkPipelineStageFlags2KHR			srcStageMask
2006 					VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,			// VkAccessFlags2KHR				srcAccessMask
2007 					VK_PIPELINE_STAGE_HOST_BIT,					// VkPipelineStageFlags2KHR			dstStageMask
2008 					VK_ACCESS_2_HOST_READ_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
2009 					**m_hostBuffer,								// VkBuffer							buffer
2010 					0u,											// VkDeviceSize						offset
2011 					m_hostBufferSizeBytes						// VkDeviceSize						size
2012 				);
2013 				VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
2014 				synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
2015 			}
2016 		}
2017 	}
2018 
getInSyncInfo(void) const2019 	SyncInfo getInSyncInfo (void) const
2020 	{
2021 		const VkAccessFlags	accessFlags = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_SHADER_READ_BIT_KHR : 0);
2022 		const SyncInfo		syncInfo	=
2023 		{
2024 			m_pipelineStage,			// VkPipelineStageFlags		stageMask;
2025 			accessFlags,				// VkAccessFlags			accessMask;
2026 			VK_IMAGE_LAYOUT_GENERAL,	// VkImageLayout			imageLayout;
2027 		};
2028 		return syncInfo;
2029 	}
2030 
getOutSyncInfo(void) const2031 	SyncInfo getOutSyncInfo (void) const
2032 	{
2033 		const VkAccessFlags	accessFlags = (m_mode == ACCESS_MODE_WRITE ? VK_ACCESS_2_SHADER_WRITE_BIT_KHR : 0);
2034 		const SyncInfo		syncInfo	=
2035 		{
2036 			m_pipelineStage,			// VkPipelineStageFlags		stageMask;
2037 			accessFlags,				// VkAccessFlags			accessMask;
2038 			VK_IMAGE_LAYOUT_GENERAL,	// VkImageLayout			imageLayout;
2039 		};
2040 		return syncInfo;
2041 	}
2042 
getData(void) const2043 	Data getData (void) const
2044 	{
2045 		return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
2046 	}
2047 
setData(const Data & data)2048 	void setData (const Data& data)
2049 	{
2050 		DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
2051 		setHostBufferData(m_context, *m_hostBuffer, data);
2052 	}
2053 
2054 private:
2055 	OperationContext&			m_context;
2056 	Resource&					m_resource;
2057 	const VkShaderStageFlagBits	m_stage;
2058 	const VkPipelineStageFlags	m_pipelineStage;
2059 	const AccessMode			m_mode;
2060 	const DispatchCall			m_dispatchCall;
2061 	const VkDeviceSize			m_hostBufferSizeBytes;
2062 	de::MovePtr<Buffer>			m_hostBuffer;
2063 	de::MovePtr<Image>			m_image;			//! Additional image used as src or dst depending on operation mode.
2064 	const VkImage*				m_srcImage;
2065 	const VkImage*				m_dstImage;
2066 	Move<VkImageView>			m_srcImageView;
2067 	Move<VkImageView>			m_dstImageView;
2068 	Move<VkDescriptorPool>		m_descriptorPool;
2069 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
2070 	Move<VkDescriptorSet>		m_descriptorSet;
2071 	de::MovePtr<Pipeline>		m_pipeline;
2072 };
2073 
2074 //! Create generic passthrough shaders with bits of custom code inserted in a specific shader stage.
initPassthroughPrograms(SourceCollections & programCollection,const std::string & shaderPrefix,const std::string & declCode,const std::string & mainCode,const VkShaderStageFlagBits stage)2075 void initPassthroughPrograms (SourceCollections&			programCollection,
2076 							  const std::string&			shaderPrefix,
2077 							  const std::string&			declCode,
2078 							  const std::string&			mainCode,
2079 							  const VkShaderStageFlagBits	stage)
2080 {
2081 	const VkShaderStageFlags	requiredStages	= getRequiredStages(stage);
2082 
2083 	if (requiredStages & VK_SHADER_STAGE_VERTEX_BIT)
2084 	{
2085 		std::ostringstream src;
2086 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2087 			<< "\n"
2088 			<< "layout(location = 0) in vec4 v_in_position;\n"
2089 			<< "\n"
2090 			<< "out " << s_perVertexBlock << ";\n"
2091 			<< "\n"
2092 			<< (stage & VK_SHADER_STAGE_VERTEX_BIT ? declCode + "\n" : "")
2093 			<< "void main (void)\n"
2094 			<< "{\n"
2095 			<< "    gl_Position = v_in_position;\n"
2096 			<< (stage & VK_SHADER_STAGE_VERTEX_BIT ? mainCode : "")
2097 			<< "}\n";
2098 
2099 		if (!programCollection.glslSources.contains(shaderPrefix + "vert"))
2100 			programCollection.glslSources.add(shaderPrefix + "vert") << glu::VertexSource(src.str());
2101 	}
2102 
2103 	if (requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
2104 	{
2105 		std::ostringstream src;
2106 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2107 			<< "\n"
2108 			<< "layout(vertices = 3) out;\n"
2109 			<< "\n"
2110 			<< "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
2111 			<< "\n"
2112 			<< "out " << s_perVertexBlock << " gl_out[];\n"
2113 			<< "\n"
2114 			<< (stage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? declCode + "\n" : "")
2115 			<< "void main (void)\n"
2116 			<< "{\n"
2117 			<< "    gl_TessLevelInner[0] = 1.0;\n"
2118 			<< "    gl_TessLevelInner[1] = 1.0;\n"
2119 			<< "\n"
2120 			<< "    gl_TessLevelOuter[0] = 1.0;\n"
2121 			<< "    gl_TessLevelOuter[1] = 1.0;\n"
2122 			<< "    gl_TessLevelOuter[2] = 1.0;\n"
2123 			<< "    gl_TessLevelOuter[3] = 1.0;\n"
2124 			<< "\n"
2125 			<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2126 			<< (stage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? "\n" + mainCode : "")
2127 			<< "}\n";
2128 
2129 		if (!programCollection.glslSources.contains(shaderPrefix + "tesc"))
2130 			programCollection.glslSources.add(shaderPrefix + "tesc") << glu::TessellationControlSource(src.str());
2131 	}
2132 
2133 	if (requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
2134 	{
2135 		std::ostringstream src;
2136 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2137 			<< "\n"
2138 			<< "layout(triangles, equal_spacing, ccw) in;\n"
2139 			<< "\n"
2140 			<< "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
2141 			<< "\n"
2142 			<< "out " << s_perVertexBlock << ";\n"
2143 			<< "\n"
2144 			<< (stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ? declCode + "\n" : "")
2145 			<< "void main (void)\n"
2146 			<< "{\n"
2147 			<< "    vec3 px = gl_TessCoord.x * gl_in[0].gl_Position.xyz;\n"
2148 			<< "    vec3 py = gl_TessCoord.y * gl_in[1].gl_Position.xyz;\n"
2149 			<< "    vec3 pz = gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
2150 			<< "    gl_Position = vec4(px + py + pz, 1.0);\n"
2151 			<< (stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ? mainCode : "")
2152 			<< "}\n";
2153 
2154 		if (!programCollection.glslSources.contains(shaderPrefix + "tese"))
2155 			programCollection.glslSources.add(shaderPrefix + "tese") << glu::TessellationEvaluationSource(src.str());
2156 	}
2157 
2158 	if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
2159 	{
2160 		std::ostringstream src;
2161 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2162 			<< "\n"
2163 			<< "layout(triangles) in;\n"
2164 			<< "layout(triangle_strip, max_vertices = 3) out;\n"
2165 			<< "\n"
2166 			<< "in " << s_perVertexBlock << " gl_in[];\n"
2167 			<< "\n"
2168 			<< "out " << s_perVertexBlock << ";\n"
2169 			<< "\n"
2170 			<< (stage & VK_SHADER_STAGE_GEOMETRY_BIT ? declCode + "\n" : "")
2171 			<< "void main (void)\n"
2172 			<< "{\n"
2173 			<< "    gl_Position = gl_in[0].gl_Position;\n"
2174 			<< "    EmitVertex();\n"
2175 			<< "\n"
2176 			<< "    gl_Position = gl_in[1].gl_Position;\n"
2177 			<< "    EmitVertex();\n"
2178 			<< "\n"
2179 			<< "    gl_Position = gl_in[2].gl_Position;\n"
2180 			<< "    EmitVertex();\n"
2181 			<< (stage & VK_SHADER_STAGE_GEOMETRY_BIT ? "\n" + mainCode : "")
2182 			<< "}\n";
2183 
2184 		if (!programCollection.glslSources.contains(shaderPrefix + "geom"))
2185 			programCollection.glslSources.add(shaderPrefix + "geom") << glu::GeometrySource(src.str());
2186 	}
2187 
2188 	if (requiredStages & VK_SHADER_STAGE_FRAGMENT_BIT)
2189 	{
2190 		std::ostringstream src;
2191 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2192 			<< "\n"
2193 			<< "layout(location = 0) out vec4 o_color;\n"
2194 			<< "\n"
2195 			<< (stage & VK_SHADER_STAGE_FRAGMENT_BIT ? declCode + "\n" : "")
2196 			<< "void main (void)\n"
2197 			<< "{\n"
2198 			<< "    o_color = vec4(1.0);\n"
2199 			<< (stage & VK_SHADER_STAGE_FRAGMENT_BIT ? "\n" + mainCode : "")
2200 			<< "}\n";
2201 
2202 		if (!programCollection.glslSources.contains(shaderPrefix + "frag"))
2203 			programCollection.glslSources.add(shaderPrefix + "frag") << glu::FragmentSource(src.str());
2204 	}
2205 
2206 	if (requiredStages & VK_SHADER_STAGE_COMPUTE_BIT)
2207 	{
2208 		std::ostringstream src;
2209 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2210 			<< "\n"
2211 			<< "layout(local_size_x = 1) in;\n"
2212 			<< "\n"
2213 			<< (stage & VK_SHADER_STAGE_COMPUTE_BIT ? declCode + "\n" : "")
2214 			<< "void main (void)\n"
2215 			<< "{\n"
2216 			<< (stage & VK_SHADER_STAGE_COMPUTE_BIT ? mainCode : "")
2217 			<< "}\n";
2218 
2219 		if (!programCollection.glslSources.contains(shaderPrefix + "comp"))
2220 			programCollection.glslSources.add(shaderPrefix + "comp") << glu::ComputeSource(src.str());
2221 	}
2222 }
2223 
2224 class BufferSupport : public OperationSupport
2225 {
2226 public:
BufferSupport(const ResourceDescription & resourceDesc,const BufferType bufferType,const AccessMode mode,const VkShaderStageFlagBits stage,const DispatchCall dispatchCall=DISPATCH_CALL_DISPATCH)2227 	BufferSupport (const ResourceDescription&	resourceDesc,
2228 				   const BufferType				bufferType,
2229 				   const AccessMode				mode,
2230 				   const VkShaderStageFlagBits	stage,
2231 				   const DispatchCall			dispatchCall = DISPATCH_CALL_DISPATCH)
2232 		: m_resourceDesc	(resourceDesc)
2233 		, m_bufferType		(bufferType)
2234 		, m_mode			(mode)
2235 		, m_stage			(stage)
2236 		, m_shaderPrefix	(std::string(m_mode == ACCESS_MODE_READ ? "read_" : "write_") + (m_bufferType == BUFFER_TYPE_UNIFORM ? "ubo_" : "ssbo_"))
2237 		, m_dispatchCall	(dispatchCall)
2238 	{
2239 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER);
2240 		DE_ASSERT(m_bufferType == BUFFER_TYPE_UNIFORM || m_bufferType == BUFFER_TYPE_STORAGE);
2241 		DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
2242 		DE_ASSERT(m_mode == ACCESS_MODE_READ || m_bufferType == BUFFER_TYPE_STORAGE);
2243 		DE_ASSERT(m_bufferType != BUFFER_TYPE_UNIFORM || m_resourceDesc.size.x() <= MAX_UBO_RANGE);
2244 		DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2245 
2246 		assertValidShaderStage(m_stage);
2247 	}
2248 
initPrograms(SourceCollections & programCollection) const2249 	void initPrograms (SourceCollections& programCollection) const
2250 	{
2251 		DE_ASSERT((m_resourceDesc.size.x() % sizeof(tcu::UVec4)) == 0);
2252 
2253 		const std::string	bufferTypeStr	= (m_bufferType == BUFFER_TYPE_UNIFORM ? "uniform" : "buffer");
2254 		const int			numVecElements	= static_cast<int>(m_resourceDesc.size.x() / sizeof(tcu::UVec4));  // std140 must be aligned to a multiple of 16
2255 
2256 		std::ostringstream declSrc;
2257 		declSrc << "layout(set = 0, binding = 0, std140) readonly " << bufferTypeStr << " Input {\n"
2258 				<< "    uvec4 data[" << numVecElements << "];\n"
2259 				<< "} b_in;\n"
2260 				<< "\n"
2261 				<< "layout(set = 0, binding = 1, std140) writeonly buffer Output {\n"
2262 				<< "    uvec4 data[" << numVecElements << "];\n"
2263 				<< "} b_out;\n";
2264 
2265 		std::ostringstream copySrc;
2266 		copySrc << "    for (int i = 0; i < " << numVecElements << "; ++i) {\n"
2267 				<< "        b_out.data[i] = b_in.data[i];\n"
2268 				<< "    }\n";
2269 
2270 		initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), copySrc.str(), m_stage);
2271 	}
2272 
getInResourceUsageFlags(void) const2273 	deUint32 getInResourceUsageFlags (void) const
2274 	{
2275 		if (m_bufferType == BUFFER_TYPE_UNIFORM)
2276 			return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : 0;
2277 		else
2278 			return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : 0;
2279 	}
2280 
getOutResourceUsageFlags(void) const2281 	deUint32 getOutResourceUsageFlags (void) const
2282 	{
2283 		if (m_bufferType == BUFFER_TYPE_UNIFORM)
2284 			return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : 0;
2285 		else
2286 			return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : 0;
2287 	}
2288 
getQueueFlags(const OperationContext & context) const2289 	VkQueueFlags getQueueFlags (const OperationContext& context) const
2290 	{
2291 		DE_UNREF(context);
2292 		return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2293 	}
2294 
build(OperationContext & context,Resource & resource) const2295 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2296 	{
2297 		if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2298 			return de::MovePtr<Operation>(new BufferImplementation(context, resource, m_stage, m_bufferType, m_shaderPrefix, m_mode, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2299 		else
2300 			return de::MovePtr<Operation>(new BufferImplementation(context, resource, m_stage, m_bufferType, m_shaderPrefix, m_mode, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2301 	}
2302 
build(OperationContext &,Resource &,Resource &) const2303 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
2304 	{
2305 		DE_ASSERT(0);
2306 		return de::MovePtr<Operation>();
2307 	}
2308 
2309 private:
2310 	const ResourceDescription	m_resourceDesc;
2311 	const BufferType			m_bufferType;
2312 	const AccessMode			m_mode;
2313 	const VkShaderStageFlagBits	m_stage;
2314 	const std::string			m_shaderPrefix;
2315 	const DispatchCall			m_dispatchCall;
2316 };
2317 
2318 class ImageSupport : public OperationSupport
2319 {
2320 public:
ImageSupport(const ResourceDescription & resourceDesc,const AccessMode mode,const VkShaderStageFlagBits stage,const DispatchCall dispatchCall=DISPATCH_CALL_DISPATCH)2321 	ImageSupport (const ResourceDescription&	resourceDesc,
2322 				  const AccessMode				mode,
2323 				  const VkShaderStageFlagBits	stage,
2324 				  const DispatchCall			dispatchCall = DISPATCH_CALL_DISPATCH)
2325 		: m_resourceDesc	(resourceDesc)
2326 		, m_mode			(mode)
2327 		, m_stage			(stage)
2328 		, m_shaderPrefix	(m_mode == ACCESS_MODE_READ ? "read_image_" : "write_image_")
2329 		, m_dispatchCall	(dispatchCall)
2330 	{
2331 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2332 		DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
2333 		DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2334 
2335 		assertValidShaderStage(m_stage);
2336 	}
2337 
initPrograms(SourceCollections & programCollection) const2338 	void initPrograms (SourceCollections& programCollection) const
2339 	{
2340 		const std::string	imageFormat	= getShaderImageFormatQualifier(m_resourceDesc.imageFormat);
2341 		const std::string	imageType	= getShaderImageType(m_resourceDesc.imageFormat, m_resourceDesc.imageType);
2342 
2343 		std::ostringstream declSrc;
2344 		declSrc << "layout(set = 0, binding = 0, " << imageFormat << ") readonly  uniform " << imageType << " srcImg;\n"
2345 				<< "layout(set = 0, binding = 1, " << imageFormat << ") writeonly uniform " << imageType << " dstImg;\n";
2346 
2347 		std::ostringstream mainSrc;
2348 		if (m_resourceDesc.imageType == VK_IMAGE_TYPE_1D)
2349 			mainSrc << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2350 					<< "        imageStore(dstImg, x, imageLoad(srcImg, x));\n";
2351 		else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_2D)
2352 			mainSrc << "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2353 					<< "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2354 					<< "        imageStore(dstImg, ivec2(x, y), imageLoad(srcImg, ivec2(x, y)));\n";
2355 		else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_3D)
2356 			mainSrc << "    for (int z = 0; z < " << m_resourceDesc.size.z() << "; ++z)\n"
2357 					<< "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2358 					<< "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2359 					<< "        imageStore(dstImg, ivec3(x, y, z), imageLoad(srcImg, ivec3(x, y, z)));\n";
2360 		else
2361 			DE_ASSERT(0);
2362 
2363 		initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), mainSrc.str(), m_stage);
2364 	}
2365 
getInResourceUsageFlags(void) const2366 	deUint32 getInResourceUsageFlags (void) const
2367 	{
2368 		return VK_IMAGE_USAGE_STORAGE_BIT;
2369 	}
2370 
getOutResourceUsageFlags(void) const2371 	deUint32 getOutResourceUsageFlags (void) const
2372 	{
2373 		return VK_IMAGE_USAGE_STORAGE_BIT;
2374 	}
2375 
getQueueFlags(const OperationContext & context) const2376 	VkQueueFlags getQueueFlags (const OperationContext& context) const
2377 	{
2378 		DE_UNREF(context);
2379 		return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2380 	}
2381 
build(OperationContext & context,Resource & resource) const2382 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2383 	{
2384 		if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2385 			return de::MovePtr<Operation>(new ImageImplementation(context, resource, m_stage, m_shaderPrefix, m_mode, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2386 		else
2387 			return de::MovePtr<Operation>(new ImageImplementation(context, resource, m_stage, m_shaderPrefix, m_mode, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2388 	}
2389 
build(OperationContext &,Resource &,Resource &) const2390 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
2391 	{
2392 		DE_ASSERT(0);
2393 		return de::MovePtr<Operation>();
2394 	}
2395 
2396 private:
2397 	const ResourceDescription	m_resourceDesc;
2398 	const AccessMode			m_mode;
2399 	const VkShaderStageFlagBits	m_stage;
2400 	const std::string			m_shaderPrefix;
2401 	const DispatchCall			m_dispatchCall;
2402 };
2403 
2404 //! Copy operation on a UBO/SSBO in graphics/compute pipeline.
2405 class BufferCopyImplementation : public Operation
2406 {
2407 public:
BufferCopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource,const VkShaderStageFlagBits stage,const BufferType bufferType,const std::string & shaderPrefix,const PipelineType pipelineType,const DispatchCall dispatchCall)2408 	BufferCopyImplementation (OperationContext&				context,
2409 							  Resource&						inResource,
2410 							  Resource&						outResource,
2411 							  const VkShaderStageFlagBits	stage,
2412 							  const BufferType				bufferType,
2413 							  const std::string&			shaderPrefix,
2414 							  const PipelineType			pipelineType,
2415 							  const DispatchCall			dispatchCall)
2416 		: m_context			(context)
2417 		, m_inResource		(inResource)
2418 		, m_outResource		(outResource)
2419 		, m_stage			(stage)
2420 		, m_pipelineStage	(pipelineStageFlagsFromShaderStageFlagBits(m_stage))
2421 		, m_bufferType		(bufferType)
2422 		, m_dispatchCall	(dispatchCall)
2423 	{
2424 		requireFeaturesForSSBOAccess (m_context, m_stage);
2425 
2426 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
2427 		const VkDevice			device		= m_context.getDevice();
2428 
2429 		// Prepare descriptors
2430 		{
2431 			const VkDescriptorType	bufferDescriptorType	= (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2432 
2433 			m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2434 				.addSingleBinding(bufferDescriptorType, m_stage)
2435 				.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
2436 				.build(vk, device);
2437 
2438 			m_descriptorPool = DescriptorPoolBuilder()
2439 				.addType(bufferDescriptorType)
2440 				.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2441 				.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2442 
2443 			m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2444 
2445 			const VkDescriptorBufferInfo  inBufferInfo = makeDescriptorBufferInfo(m_inResource.getBuffer().handle, m_inResource.getBuffer().offset, m_inResource.getBuffer().size);
2446 			const VkDescriptorBufferInfo  outBufferInfo	 = makeDescriptorBufferInfo(m_outResource.getBuffer().handle, m_outResource.getBuffer().offset, m_outResource.getBuffer().size);
2447 
2448 			DescriptorSetUpdateBuilder()
2449 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inBufferInfo)
2450 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferInfo)
2451 				.update(vk, device);
2452 		}
2453 
2454 		// Create pipeline
2455 		m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
2456 															 : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
2457 	}
2458 
recordCommands(const VkCommandBuffer cmdBuffer)2459 	void recordCommands (const VkCommandBuffer cmdBuffer)
2460 	{
2461 		m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
2462 	}
2463 
getInSyncInfo(void) const2464 	SyncInfo getInSyncInfo (void) const
2465 	{
2466 		const SyncInfo		syncInfo	=
2467 		{
2468 			m_pipelineStage,					// VkPipelineStageFlags		stageMask;
2469 			VK_ACCESS_2_SHADER_READ_BIT_KHR,	// VkAccessFlags			accessMask;
2470 			VK_IMAGE_LAYOUT_UNDEFINED,			// VkImageLayout			imageLayout;
2471 		};
2472 		return syncInfo;
2473 	}
2474 
getOutSyncInfo(void) const2475 	SyncInfo getOutSyncInfo (void) const
2476 	{
2477 		const SyncInfo		syncInfo	=
2478 		{
2479 			m_pipelineStage,					// VkPipelineStageFlags		stageMask;
2480 			VK_ACCESS_2_SHADER_WRITE_BIT_KHR,	// VkAccessFlags			accessMask;
2481 			VK_IMAGE_LAYOUT_UNDEFINED,			// VkImageLayout			imageLayout;
2482 		};
2483 		return syncInfo;
2484 	}
2485 
getData(void) const2486 	Data getData (void) const
2487 	{
2488 		Data data = { 0, DE_NULL };
2489 		return data;
2490 	}
2491 
setData(const Data &)2492 	void setData (const Data&)
2493 	{
2494 		DE_ASSERT(0);
2495 	}
2496 
2497 private:
2498 	OperationContext&			m_context;
2499 	Resource&					m_inResource;
2500 	Resource&					m_outResource;
2501 	const VkShaderStageFlagBits	m_stage;
2502 	const VkPipelineStageFlags	m_pipelineStage;
2503 	const BufferType			m_bufferType;
2504 	const DispatchCall			m_dispatchCall;
2505 	Move<VkDescriptorPool>		m_descriptorPool;
2506 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
2507 	Move<VkDescriptorSet>		m_descriptorSet;
2508 	de::MovePtr<Pipeline>		m_pipeline;
2509 };
2510 
2511 class CopyBufferSupport : public OperationSupport
2512 {
2513 public:
CopyBufferSupport(const ResourceDescription & resourceDesc,const BufferType bufferType,const VkShaderStageFlagBits stage,const DispatchCall dispatchCall=DISPATCH_CALL_DISPATCH)2514 	CopyBufferSupport (const ResourceDescription&	resourceDesc,
2515 					   const BufferType				bufferType,
2516 					   const VkShaderStageFlagBits	stage,
2517 					   const DispatchCall			dispatchCall = DISPATCH_CALL_DISPATCH)
2518 		: m_resourceDesc	(resourceDesc)
2519 		, m_bufferType		(bufferType)
2520 		, m_stage			(stage)
2521 		, m_shaderPrefix	(std::string("copy_") + getShaderStageName(stage) + (m_bufferType == BUFFER_TYPE_UNIFORM ? "_ubo_" : "_ssbo_"))
2522 		, m_dispatchCall	(dispatchCall)
2523 	{
2524 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER);
2525 		DE_ASSERT(m_bufferType == BUFFER_TYPE_UNIFORM || m_bufferType == BUFFER_TYPE_STORAGE);
2526 		DE_ASSERT(m_bufferType != BUFFER_TYPE_UNIFORM || m_resourceDesc.size.x() <= MAX_UBO_RANGE);
2527 		DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2528 
2529 		assertValidShaderStage(m_stage);
2530 	}
2531 
initPrograms(SourceCollections & programCollection) const2532 	void initPrograms (SourceCollections& programCollection) const
2533 	{
2534 		DE_ASSERT((m_resourceDesc.size.x() % sizeof(tcu::UVec4)) == 0);
2535 
2536 		const std::string	bufferTypeStr	= (m_bufferType == BUFFER_TYPE_UNIFORM ? "uniform" : "buffer");
2537 		const int			numVecElements	= static_cast<int>(m_resourceDesc.size.x() / sizeof(tcu::UVec4));  // std140 must be aligned to a multiple of 16
2538 
2539 		std::ostringstream declSrc;
2540 		declSrc << "layout(set = 0, binding = 0, std140) readonly " << bufferTypeStr << " Input {\n"
2541 				<< "    uvec4 data[" << numVecElements << "];\n"
2542 				<< "} b_in;\n"
2543 				<< "\n"
2544 				<< "layout(set = 0, binding = 1, std140) writeonly buffer Output {\n"
2545 				<< "    uvec4 data[" << numVecElements << "];\n"
2546 				<< "} b_out;\n";
2547 
2548 		std::ostringstream copySrc;
2549 		copySrc << "    for (int i = 0; i < " << numVecElements << "; ++i) {\n"
2550 				<< "        b_out.data[i] = b_in.data[i];\n"
2551 				<< "    }\n";
2552 
2553 		initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), copySrc.str(), m_stage);
2554 	}
2555 
getInResourceUsageFlags(void) const2556 	deUint32 getInResourceUsageFlags (void) const
2557 	{
2558 		return (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2559 	}
2560 
getOutResourceUsageFlags(void) const2561 	deUint32 getOutResourceUsageFlags (void) const
2562 	{
2563 		return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
2564 	}
2565 
getQueueFlags(const OperationContext & context) const2566 	VkQueueFlags getQueueFlags (const OperationContext& context) const
2567 	{
2568 		DE_UNREF(context);
2569 		return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2570 	}
2571 
build(OperationContext &,Resource &) const2572 	de::MovePtr<Operation> build (OperationContext&, Resource&) const
2573 	{
2574 		DE_ASSERT(0);
2575 		return de::MovePtr<Operation>();
2576 	}
2577 
build(OperationContext & context,Resource & inResource,Resource & outResource) const2578 	de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
2579 	{
2580 		if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2581 			return de::MovePtr<Operation>(new BufferCopyImplementation(context, inResource, outResource, m_stage, m_bufferType, m_shaderPrefix, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2582 		else
2583 			return de::MovePtr<Operation>(new BufferCopyImplementation(context, inResource, outResource, m_stage, m_bufferType, m_shaderPrefix, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2584 	}
2585 
2586 private:
2587 	const ResourceDescription	m_resourceDesc;
2588 	const BufferType			m_bufferType;
2589 	const VkShaderStageFlagBits	m_stage;
2590 	const std::string			m_shaderPrefix;
2591 	const DispatchCall			m_dispatchCall;
2592 };
2593 
2594 class CopyImageImplementation : public Operation
2595 {
2596 public:
CopyImageImplementation(OperationContext & context,Resource & inResource,Resource & outResource,const VkShaderStageFlagBits stage,const std::string & shaderPrefix,const PipelineType pipelineType,const DispatchCall dispatchCall)2597 	CopyImageImplementation (OperationContext&				context,
2598 							 Resource&						inResource,
2599 							 Resource&						outResource,
2600 							 const VkShaderStageFlagBits	stage,
2601 							 const std::string&				shaderPrefix,
2602 							 const PipelineType				pipelineType,
2603 							 const DispatchCall				dispatchCall)
2604 		: m_context				(context)
2605 		, m_inResource			(inResource)
2606 		, m_outResource			(outResource)
2607 		, m_stage				(stage)
2608 		, m_pipelineStage		(pipelineStageFlagsFromShaderStageFlagBits(m_stage))
2609 		, m_dispatchCall		(dispatchCall)
2610 	{
2611 		const DeviceInterface&		vk			= m_context.getDeviceInterface();
2612 		const InstanceInterface&	vki			= m_context.getInstanceInterface();
2613 		const VkDevice				device		= m_context.getDevice();
2614 		const VkPhysicalDevice		physDevice	= m_context.getPhysicalDevice();
2615 
2616 		// Image stores are always required, in either access mode.
2617 		requireFeaturesForSSBOAccess(m_context, m_stage);
2618 
2619 		// Some storage image formats may not be supported
2620 		const auto& imgResource = m_inResource.getImage();
2621 		requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
2622 
2623 		// Image resources
2624 		{
2625 			const VkImageViewType viewType = getImageViewType(m_inResource.getImage().imageType);
2626 
2627 			m_srcImageView	= makeImageView(vk, device, m_inResource.getImage().handle, viewType, m_inResource.getImage().format, m_inResource.getImage().subresourceRange);
2628 			m_dstImageView	= makeImageView(vk, device, m_outResource.getImage().handle, viewType, m_outResource.getImage().format, m_outResource.getImage().subresourceRange);
2629 		}
2630 
2631 		// Prepare descriptors
2632 		{
2633 			m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2634 				.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
2635 				.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
2636 				.build(vk, device);
2637 
2638 			m_descriptorPool = DescriptorPoolBuilder()
2639 				.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2640 				.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2641 				.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2642 
2643 			m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2644 
2645 			const VkDescriptorImageInfo srcImageInfo = makeDescriptorImageInfo(DE_NULL, *m_srcImageView, VK_IMAGE_LAYOUT_GENERAL);
2646 			const VkDescriptorImageInfo dstImageInfo = makeDescriptorImageInfo(DE_NULL, *m_dstImageView, VK_IMAGE_LAYOUT_GENERAL);
2647 
2648 			DescriptorSetUpdateBuilder()
2649 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &srcImageInfo)
2650 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &dstImageInfo)
2651 				.update(vk, device);
2652 		}
2653 
2654 		// Create pipeline
2655 		m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
2656 															 : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
2657 	}
2658 
recordCommands(const VkCommandBuffer cmdBuffer)2659 	void recordCommands (const VkCommandBuffer cmdBuffer)
2660 	{
2661 		{
2662 			const DeviceInterface&		vk						= m_context.getDeviceInterface();
2663 			SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
2664 
2665 			const VkImageMemoryBarrier2KHR imageMemoryBarriers2 = makeImageMemoryBarrier2(
2666 					VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags2KHR			srcStageMask
2667 					(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
2668 					m_pipelineStage,								// VkPipelineStageFlags2KHR			dstStageMask
2669 					VK_ACCESS_2_SHADER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
2670 					VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
2671 					VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout					newLayout
2672 					m_outResource.getImage().handle,				// VkImage							image
2673 					m_outResource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
2674 			);
2675 			VkDependencyInfoKHR dependencyInfo
2676 			{
2677 				VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,				// VkStructureType					sType
2678 				DE_NULL,											// const void*						pNext
2679 				VK_DEPENDENCY_BY_REGION_BIT,						// VkDependencyFlags				dependencyFlags
2680 				0u,													// deUint32							memoryBarrierCount
2681 				DE_NULL,											// const VkMemoryBarrier2KHR*		pMemoryBarriers
2682 				0u,													// deUint32							bufferMemoryBarrierCount
2683 				DE_NULL,											// const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers
2684 				1,													// deUint32							imageMemoryBarrierCount
2685 				&imageMemoryBarriers2								// const VkImageMemoryBarrier2KHR*	pImageMemoryBarriers
2686 			};
2687 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
2688 		}
2689 
2690 		// Execute shaders
2691 		m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
2692 	}
2693 
getInSyncInfo(void) const2694 	SyncInfo getInSyncInfo (void) const
2695 	{
2696 		const SyncInfo		syncInfo	=
2697 		{
2698 			m_pipelineStage,					// VkPipelineStageFlags		stageMask;
2699 			VK_ACCESS_2_SHADER_READ_BIT_KHR,	// VkAccessFlags			accessMask;
2700 			VK_IMAGE_LAYOUT_GENERAL,			// VkImageLayout			imageLayout;
2701 		};
2702 		return syncInfo;
2703 	}
2704 
getOutSyncInfo(void) const2705 	SyncInfo getOutSyncInfo (void) const
2706 	{
2707 		const SyncInfo		syncInfo	=
2708 		{
2709 			m_pipelineStage,					// VkPipelineStageFlags		stageMask;
2710 			VK_ACCESS_2_SHADER_WRITE_BIT_KHR,	// VkAccessFlags			accessMask;
2711 			VK_IMAGE_LAYOUT_GENERAL,			// VkImageLayout			imageLayout;
2712 		};
2713 		return syncInfo;
2714 	}
2715 
getData(void) const2716 	Data getData (void) const
2717 	{
2718 		Data data = { 0, DE_NULL };
2719 		return data;
2720 	}
2721 
setData(const Data &)2722 	void setData (const Data&)
2723 	{
2724 		DE_ASSERT(0);
2725 	}
2726 
2727 private:
2728 	OperationContext&			m_context;
2729 	Resource&					m_inResource;
2730 	Resource&					m_outResource;
2731 	const VkShaderStageFlagBits	m_stage;
2732 	const VkPipelineStageFlags	m_pipelineStage;
2733 	const DispatchCall			m_dispatchCall;
2734 	Move<VkImageView>			m_srcImageView;
2735 	Move<VkImageView>			m_dstImageView;
2736 	Move<VkDescriptorPool>		m_descriptorPool;
2737 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
2738 	Move<VkDescriptorSet>		m_descriptorSet;
2739 	de::MovePtr<Pipeline>		m_pipeline;
2740 };
2741 
2742 class CopyImageSupport : public OperationSupport
2743 {
2744 public:
CopyImageSupport(const ResourceDescription & resourceDesc,const VkShaderStageFlagBits stage,const DispatchCall dispatchCall=DISPATCH_CALL_DISPATCH)2745 	CopyImageSupport (const ResourceDescription&	resourceDesc,
2746 					  const VkShaderStageFlagBits	stage,
2747 					  const DispatchCall			dispatchCall = DISPATCH_CALL_DISPATCH)
2748 		: m_resourceDesc	(resourceDesc)
2749 		, m_stage			(stage)
2750 		, m_shaderPrefix	(std::string("copy_image_") + getShaderStageName(stage) + "_")
2751 		, m_dispatchCall	(dispatchCall)
2752 	{
2753 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2754 		DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2755 
2756 		assertValidShaderStage(m_stage);
2757 	}
2758 
initPrograms(SourceCollections & programCollection) const2759 	void initPrograms (SourceCollections& programCollection) const
2760 	{
2761 		const std::string	imageFormat	= getShaderImageFormatQualifier(m_resourceDesc.imageFormat);
2762 		const std::string	imageType	= getShaderImageType(m_resourceDesc.imageFormat, m_resourceDesc.imageType);
2763 
2764 		std::ostringstream declSrc;
2765 		declSrc << "layout(set = 0, binding = 0, " << imageFormat << ") readonly  uniform " << imageType << " srcImg;\n"
2766 				<< "layout(set = 0, binding = 1, " << imageFormat << ") writeonly uniform " << imageType << " dstImg;\n";
2767 
2768 		std::ostringstream mainSrc;
2769 		if (m_resourceDesc.imageType == VK_IMAGE_TYPE_1D)
2770 			mainSrc << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2771 					<< "        imageStore(dstImg, x, imageLoad(srcImg, x));\n";
2772 		else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_2D)
2773 			mainSrc << "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2774 					<< "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2775 					<< "        imageStore(dstImg, ivec2(x, y), imageLoad(srcImg, ivec2(x, y)));\n";
2776 		else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_3D)
2777 			mainSrc << "    for (int z = 0; z < " << m_resourceDesc.size.z() << "; ++z)\n"
2778 					<< "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2779 					<< "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2780 					<< "        imageStore(dstImg, ivec3(x, y, z), imageLoad(srcImg, ivec3(x, y, z)));\n";
2781 		else
2782 			DE_ASSERT(0);
2783 
2784 		initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), mainSrc.str(), m_stage);
2785 	}
2786 
getInResourceUsageFlags(void) const2787 	deUint32 getInResourceUsageFlags (void) const
2788 	{
2789 		return VK_IMAGE_USAGE_STORAGE_BIT;
2790 	}
2791 
getOutResourceUsageFlags(void) const2792 	deUint32 getOutResourceUsageFlags (void) const
2793 	{
2794 		return VK_IMAGE_USAGE_STORAGE_BIT;
2795 	}
2796 
getQueueFlags(const OperationContext & context) const2797 	VkQueueFlags getQueueFlags (const OperationContext& context) const
2798 	{
2799 		DE_UNREF(context);
2800 		return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2801 	}
2802 
build(OperationContext &,Resource &) const2803 	de::MovePtr<Operation> build (OperationContext&, Resource&) const
2804 	{
2805 		DE_ASSERT(0);
2806 		return de::MovePtr<Operation>();
2807 	}
2808 
build(OperationContext & context,Resource & inResource,Resource & outResource) const2809 	de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
2810 	{
2811 		if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2812 			return de::MovePtr<Operation>(new CopyImageImplementation(context, inResource, outResource, m_stage, m_shaderPrefix, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2813 		else
2814 			return de::MovePtr<Operation>(new CopyImageImplementation(context, inResource, outResource, m_stage, m_shaderPrefix, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2815 	}
2816 
2817 private:
2818 	const ResourceDescription	m_resourceDesc;
2819 	const VkShaderStageFlagBits	m_stage;
2820 	const std::string			m_shaderPrefix;
2821 	const DispatchCall			m_dispatchCall;
2822 };
2823 
2824 class MSImageImplementation : public Operation
2825 {
2826 public:
MSImageImplementation(OperationContext & context,Resource & resource)2827 	MSImageImplementation(OperationContext&	context,
2828 						  Resource&			resource)
2829 		: m_context		(context)
2830 		, m_resource	(resource)
2831 		, m_hostBufferSizeBytes(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
2832 	{
2833 		const DeviceInterface&			vk			= m_context.getDeviceInterface();
2834 		const InstanceInterface&		vki			= m_context.getInstanceInterface();
2835 		const VkDevice					device		= m_context.getDevice();
2836 		const VkPhysicalDevice			physDevice	= m_context.getPhysicalDevice();
2837 		const VkPhysicalDeviceFeatures	features	= getPhysicalDeviceFeatures(vki, physDevice);
2838 		Allocator&						allocator	= m_context.getAllocator();
2839 
2840 		const auto& imgResource = m_resource.getImage();
2841 		requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
2842 		if (!features.shaderStorageImageMultisample)
2843 			TCU_THROW(NotSupportedError, "Using multisample images as storage is not supported");
2844 
2845 		VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2846 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
2847 		const Allocation& alloc = m_hostBuffer->getAllocation();
2848 		fillPattern(alloc.getHostPtr(), m_hostBufferSizeBytes);
2849 		flushAlloc(vk, device, alloc);
2850 
2851 		const ImageResource&  image		= m_resource.getImage();
2852 		const VkImageViewType viewType	= getImageViewType(image.imageType);
2853 		m_imageView = makeImageView(vk, device, image.handle, viewType, image.format, image.subresourceRange);
2854 
2855 		// Prepare descriptors
2856 		{
2857 			m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2858 				.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
2859 				.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,  VK_SHADER_STAGE_COMPUTE_BIT)
2860 				.build(vk, device);
2861 
2862 			m_descriptorPool = DescriptorPoolBuilder()
2863 				.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2864 				.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2865 				.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2866 
2867 			m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2868 
2869 			const VkDescriptorBufferInfo bufferInfo	= makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_hostBufferSizeBytes);
2870 			const VkDescriptorImageInfo  imageInfo	= makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
2871 
2872 			DescriptorSetUpdateBuilder()
2873 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
2874 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,  &imageInfo)
2875 				.update(vk, device);
2876 		}
2877 
2878 		// Create pipeline
2879 		const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get("comp"), (VkShaderModuleCreateFlags)0));
2880 		m_pipelineLayout	= makePipelineLayout (vk, device, *m_descriptorSetLayout);
2881 		m_pipeline			= makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData(), context.getResourceInterface());
2882 	}
2883 
recordCommands(const VkCommandBuffer cmdBuffer)2884 	void recordCommands(const VkCommandBuffer cmdBuffer)
2885 	{
2886 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
2887 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
2888 
2889 		// change image layout
2890 		{
2891 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
2892 				VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,	// VkPipelineStageFlags2KHR			srcStageMask
2893 				(VkAccessFlags)0,							// VkAccessFlags2KHR				srcAccessMask
2894 				VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR,	// VkPipelineStageFlags2KHR			dstStageMask
2895 				VK_ACCESS_2_SHADER_WRITE_BIT_KHR,			// VkAccessFlags2KHR				dstAccessMask
2896 				VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					oldLayout
2897 				VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					newLayout
2898 				m_resource.getImage().handle,				// VkImage							image
2899 				m_resource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
2900 			);
2901 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
2902 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
2903 		}
2904 
2905 		// execute shader
2906 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
2907 		vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
2908 		vk.cmdDispatch(cmdBuffer, m_resource.getImage().extent.width, m_resource.getImage().extent.height, 1u);
2909 	}
2910 
getInSyncInfo(void) const2911 	SyncInfo getInSyncInfo(void) const
2912 	{
2913 		DE_ASSERT(false);
2914 		return emptySyncInfo;
2915 	}
2916 
getOutSyncInfo(void) const2917 	SyncInfo getOutSyncInfo(void) const
2918 	{
2919 		return
2920 		{
2921 			VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
2922 			VK_ACCESS_2_SHADER_WRITE_BIT_KHR,			// VkAccessFlags			accessMask;
2923 			VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			imageLayout;
2924 		};
2925 	}
2926 
getData(void) const2927 	Data getData(void) const
2928 	{
2929 		return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
2930 	}
2931 
setData(const Data &)2932 	void setData(const Data&)
2933 	{
2934 		DE_ASSERT(false);
2935 	}
2936 
2937 private:
2938 	OperationContext&			m_context;
2939 	Resource&					m_resource;
2940 	Move<VkImageView>			m_imageView;
2941 
2942 	const VkDeviceSize			m_hostBufferSizeBytes;
2943 	de::MovePtr<Buffer>			m_hostBuffer;
2944 
2945 	Move<VkDescriptorPool>		m_descriptorPool;
2946 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
2947 	Move<VkDescriptorSet>		m_descriptorSet;
2948 	Move<VkPipelineLayout>		m_pipelineLayout;
2949 	Move<VkPipeline>			m_pipeline;
2950 };
2951 
2952 class MSImageSupport : public OperationSupport
2953 {
2954 public:
MSImageSupport(const ResourceDescription & resourceDesc)2955 	MSImageSupport(const ResourceDescription& resourceDesc)
2956 		: m_resourceDesc	(resourceDesc)
2957 	{
2958 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2959 	}
2960 
initPrograms(SourceCollections & programCollection) const2961 	void initPrograms (SourceCollections& programCollection) const
2962 	{
2963 		std::stringstream source;
2964 		source <<
2965 			"#version 440\n"
2966 			"\n"
2967 			"layout(local_size_x = 1) in;\n"
2968 			"layout(set = 0, binding = 0, std430) readonly buffer Input {\n"
2969 			"    uint data[];\n"
2970 			"} inData;\n"
2971 			"layout(set = 0, binding = 1, r32ui) writeonly uniform uimage2DMS msImage;\n"
2972 			"\n"
2973 			"void main (void)\n"
2974 			"{\n"
2975 			"  int  gx    = int(gl_GlobalInvocationID.x);\n"
2976 			"  int  gy    = int(gl_GlobalInvocationID.y);\n"
2977 			"  uint value = inData.data[gy * " << m_resourceDesc.size.x() << " + gx];\n"
2978 			"  for (int sampleNdx = 0; sampleNdx < " << m_resourceDesc.imageSamples << "; ++sampleNdx)\n"
2979 			"    imageStore(msImage, ivec2(gx, gy), sampleNdx, uvec4(value));\n"
2980 			"}\n";
2981 		programCollection.glslSources.add("comp") << glu::ComputeSource(source.str().c_str());
2982 	}
2983 
getInResourceUsageFlags(void) const2984 	deUint32 getInResourceUsageFlags (void) const
2985 	{
2986 		return 0;
2987 	}
2988 
getOutResourceUsageFlags(void) const2989 	deUint32 getOutResourceUsageFlags (void) const
2990 	{
2991 		return VK_IMAGE_USAGE_STORAGE_BIT;
2992 	}
2993 
getQueueFlags(const OperationContext &) const2994 	VkQueueFlags getQueueFlags (const OperationContext&) const
2995 	{
2996 		return VK_QUEUE_COMPUTE_BIT;
2997 	}
2998 
build(OperationContext & context,Resource & resource) const2999 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3000 	{
3001 		return de::MovePtr<Operation>(new MSImageImplementation(context, resource));
3002 	}
3003 
build(OperationContext &,Resource &,Resource &) const3004 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3005 	{
3006 		DE_ASSERT(0);
3007 		return de::MovePtr<Operation>();
3008 	}
3009 
3010 private:
3011 	const ResourceDescription	m_resourceDesc;
3012 };
3013 
3014 } // ShaderAccess ns
3015 
3016 namespace CopyBufferToImage
3017 {
3018 
3019 class WriteImplementation : public Operation
3020 {
3021 public:
WriteImplementation(OperationContext & context,Resource & resource)3022 	WriteImplementation (OperationContext& context, Resource& resource)
3023 		: m_context		(context)
3024 		, m_resource	(resource)
3025 		, m_bufferSize	(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
3026 	{
3027 		DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_IMAGE);
3028 
3029 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
3030 		const VkDevice			device		= m_context.getDevice();
3031 		Allocator&				allocator	= m_context.getAllocator();
3032 
3033 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3034 			vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible));
3035 
3036 		const Allocation& alloc = m_hostBuffer->getAllocation();
3037 		fillPattern(alloc.getHostPtr(), m_bufferSize);
3038 		flushAlloc(vk, device, alloc);
3039 	}
3040 
recordCommands(const VkCommandBuffer cmdBuffer)3041 	void recordCommands (const VkCommandBuffer cmdBuffer)
3042 	{
3043 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
3044 		const VkBufferImageCopy		copyRegion				= makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
3045 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3046 
3047 		const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3048 			VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,			// VkPipelineStageFlags2KHR			srcStageMask
3049 			(VkAccessFlags)0,									// VkAccessFlags2KHR				srcAccessMask
3050 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,				// VkPipelineStageFlags2KHR			dstStageMask
3051 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,					// VkAccessFlags2KHR				dstAccessMask
3052 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					oldLayout
3053 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout					newLayout
3054 			m_resource.getImage().handle,						// VkImage							image
3055 			m_resource.getImage().subresourceRange				// VkImageSubresourceRange			subresourceRange
3056 		);
3057 		VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3058 		synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3059 
3060 		vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
3061 	}
3062 
getInSyncInfo(void) const3063 	SyncInfo getInSyncInfo (void) const
3064 	{
3065 		return emptySyncInfo;
3066 	}
3067 
getOutSyncInfo(void) const3068 	SyncInfo getOutSyncInfo (void) const
3069 	{
3070 		const SyncInfo syncInfo =
3071 		{
3072 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
3073 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,		// VkAccessFlags			accessMask;
3074 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			imageLayout;
3075 		};
3076 		return syncInfo;
3077 	}
3078 
getData(void) const3079 	Data getData (void) const
3080 	{
3081 		return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
3082 	}
3083 
setData(const Data & data)3084 	void setData (const Data& data)
3085 	{
3086 		setHostBufferData(m_context, *m_hostBuffer, data);
3087 	}
3088 
3089 private:
3090 	OperationContext&		m_context;
3091 	Resource&				m_resource;
3092 	de::MovePtr<Buffer>		m_hostBuffer;
3093 	const VkDeviceSize		m_bufferSize;
3094 };
3095 
3096 class ReadImplementation : public Operation
3097 {
3098 public:
ReadImplementation(OperationContext & context,Resource & resource)3099 	ReadImplementation (OperationContext& context, Resource& resource)
3100 		: m_context				(context)
3101 		, m_resource			(resource)
3102 		, m_subresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
3103 		, m_subresourceLayers	(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
3104 	{
3105 		DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_BUFFER);
3106 
3107 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
3108 		const VkDevice			device		= m_context.getDevice();
3109 		Allocator&				allocator	= m_context.getAllocator();
3110 		const VkFormat			format		= VK_FORMAT_R8G8B8A8_UNORM;
3111 		const deUint32			pixelSize	= tcu::getPixelSize(mapVkFormat(format));
3112 
3113 		DE_ASSERT((m_resource.getBuffer().size % pixelSize) == 0);
3114 		m_imageExtent = get2DImageExtentWithSize(m_resource.getBuffer().size, pixelSize);  // there may be some unused space at the end
3115 
3116 		// Copy destination image.
3117 		m_image = de::MovePtr<Image>(new Image(
3118 			vk, device, allocator,
3119 			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format,
3120 								(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
3121 								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
3122 			MemoryRequirement::Any));
3123 
3124 		// Image data will be copied here, so it can be read on the host.
3125 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3126 			vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
3127 	}
3128 
recordCommands(const VkCommandBuffer cmdBuffer)3129 	void recordCommands (const VkCommandBuffer cmdBuffer)
3130 	{
3131 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
3132 		const VkBufferImageCopy		copyRegion				= makeBufferImageCopy(m_imageExtent, m_subresourceLayers);
3133 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3134 
3135 		// Resource -> Image
3136 		{
3137 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3138 				VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,			// VkPipelineStageFlags2KHR			srcStageMask
3139 				(VkAccessFlags)0,									// VkAccessFlags2KHR				srcAccessMask
3140 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,				// VkPipelineStageFlags2KHR			dstStageMask
3141 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,					// VkAccessFlags2KHR				dstAccessMask
3142 				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					oldLayout
3143 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout					newLayout
3144 				**m_image,											// VkImage							image
3145 				m_subresourceRange									// VkImageSubresourceRange			subresourceRange
3146 			);
3147 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3148 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3149 
3150 			vk.cmdCopyBufferToImage(cmdBuffer, m_resource.getBuffer().handle, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
3151 		}
3152 		// Image -> Host buffer
3153 		{
3154 			const VkImageMemoryBarrier2KHR imageLayoutBarrier2 = makeImageMemoryBarrier2(
3155 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,				// VkPipelineStageFlags2KHR			srcStageMask
3156 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,					// VkAccessFlags2KHR				srcAccessMask
3157 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,				// VkPipelineStageFlags2KHR			dstStageMask
3158 				VK_ACCESS_2_TRANSFER_READ_BIT_KHR,					// VkAccessFlags2KHR				dstAccessMask
3159 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout					oldLayout
3160 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,				// VkImageLayout					newLayout
3161 				**m_image,											// VkImage							image
3162 				m_subresourceRange									// VkImageSubresourceRange			subresourceRange
3163 			);
3164 			VkDependencyInfoKHR layoutDependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageLayoutBarrier2);
3165 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &layoutDependencyInfo);
3166 
3167 			vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &copyRegion);
3168 
3169 			const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3170 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,				// VkPipelineStageFlags2KHR			srcStageMask
3171 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,					// VkAccessFlags2KHR				srcAccessMask
3172 				VK_PIPELINE_STAGE_2_HOST_BIT_KHR,					// VkPipelineStageFlags2KHR			dstStageMask
3173 				VK_ACCESS_2_HOST_READ_BIT_KHR,						// VkAccessFlags2KHR				dstAccessMask
3174 				**m_hostBuffer,										// VkBuffer							buffer
3175 				0u,													// VkDeviceSize						offset
3176 				m_resource.getBuffer().size							// VkDeviceSize						size
3177 			);
3178 			VkDependencyInfoKHR bufferDependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
3179 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &bufferDependencyInfo);
3180 		}
3181 	}
3182 
getInSyncInfo(void) const3183 	SyncInfo getInSyncInfo (void) const
3184 	{
3185 		const SyncInfo syncInfo =
3186 		{
3187 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
3188 			VK_ACCESS_2_TRANSFER_READ_BIT_KHR,		// VkAccessFlags			accessMask;
3189 			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			imageLayout;
3190 		};
3191 		return syncInfo;
3192 	}
3193 
getOutSyncInfo(void) const3194 	SyncInfo getOutSyncInfo (void) const
3195 	{
3196 		return emptySyncInfo;
3197 	}
3198 
getData(void) const3199 	Data getData (void) const
3200 	{
3201 		return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
3202 	}
3203 
setData(const Data & data)3204 	void setData (const Data& data)
3205 	{
3206 		setHostBufferData(m_context, *m_hostBuffer, data);
3207 	}
3208 
3209 private:
3210 	OperationContext&				m_context;
3211 	Resource&						m_resource;
3212 	const VkImageSubresourceRange	m_subresourceRange;
3213 	const VkImageSubresourceLayers	m_subresourceLayers;
3214 	de::MovePtr<Buffer>				m_hostBuffer;
3215 	de::MovePtr<Image>				m_image;
3216 	VkExtent3D						m_imageExtent;
3217 };
3218 
3219 class Support : public OperationSupport
3220 {
3221 public:
Support(const ResourceDescription & resourceDesc,const AccessMode mode)3222 	Support (const ResourceDescription& resourceDesc, const AccessMode mode)
3223 		: m_mode				(mode)
3224 		, m_resourceType		(resourceDesc.type)
3225 		, m_requiredQueueFlags	(resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
3226 	{
3227 		// From spec:
3228 		//   Because depth or stencil aspect buffer to image copies may require format conversions on some implementations,
3229 		//   they are not supported on queues that do not support graphics.
3230 
3231 		DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
3232 		DE_ASSERT(m_mode == ACCESS_MODE_READ || resourceDesc.type != RESOURCE_TYPE_BUFFER);
3233 		DE_ASSERT(m_mode == ACCESS_MODE_WRITE || resourceDesc.type != RESOURCE_TYPE_IMAGE);
3234 	}
3235 
getInResourceUsageFlags(void) const3236 	deUint32 getInResourceUsageFlags (void) const
3237 	{
3238 		if (m_resourceType == RESOURCE_TYPE_IMAGE)
3239 			return m_mode == ACCESS_MODE_READ ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : 0;
3240 		else
3241 			return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0;
3242 	}
3243 
getOutResourceUsageFlags(void) const3244 	deUint32 getOutResourceUsageFlags (void) const
3245 	{
3246 		if (m_resourceType == RESOURCE_TYPE_IMAGE)
3247 			return m_mode == ACCESS_MODE_WRITE ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0;
3248 		else
3249 			return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0;
3250 	}
3251 
getQueueFlags(const OperationContext & context) const3252 	VkQueueFlags getQueueFlags (const OperationContext& context) const
3253 	{
3254 		DE_UNREF(context);
3255 		return m_requiredQueueFlags;
3256 	}
3257 
build(OperationContext & context,Resource & resource) const3258 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3259 	{
3260 		if (m_mode == ACCESS_MODE_READ)
3261 			return de::MovePtr<Operation>(new ReadImplementation(context, resource));
3262 		else
3263 			return de::MovePtr<Operation>(new WriteImplementation(context, resource));
3264 	}
3265 
build(OperationContext &,Resource &,Resource &) const3266 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3267 	{
3268 		DE_ASSERT(0);
3269 		return de::MovePtr<Operation>();
3270 	}
3271 
3272 private:
3273 	const AccessMode			m_mode;
3274 	const enum ResourceType		m_resourceType;
3275 	const VkQueueFlags			m_requiredQueueFlags;
3276 };
3277 
3278 class CopyImplementation : public Operation
3279 {
3280 public:
CopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)3281 	CopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
3282 		: m_context		(context)
3283 		, m_inResource	(inResource)
3284 		, m_outResource	(outResource)
3285 	{
3286 		DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_BUFFER);
3287 		DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_IMAGE);
3288 	}
3289 
recordCommands(const VkCommandBuffer cmdBuffer)3290 	void recordCommands (const VkCommandBuffer cmdBuffer)
3291 	{
3292 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
3293 		const VkBufferImageCopy		copyRegion				= makeBufferImageCopy(m_outResource.getImage().extent, m_outResource.getImage().subresourceLayers);
3294 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3295 
3296 		const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3297 			VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,		// VkPipelineStageFlags2KHR			srcStageMask
3298 			(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
3299 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
3300 			VK_ACCESS_2_TRANSFER_READ_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
3301 			m_inResource.getBuffer().handle,				// VkBuffer							buffer
3302 			0u,												// VkDeviceSize						offset
3303 			m_inResource.getBuffer().size					// VkDeviceSize						size
3304 		);
3305 		const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3306 			VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,		// VkPipelineStageFlags2KHR			srcStageMask
3307 			(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
3308 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
3309 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
3310 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
3311 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					newLayout
3312 			m_outResource.getImage().handle,				// VkImage							image
3313 			m_outResource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
3314 		);
3315 		VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2, &imageMemoryBarrier2);
3316 		synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3317 
3318 		vk.cmdCopyBufferToImage(cmdBuffer, m_inResource.getBuffer().handle, m_outResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
3319 	}
3320 
getInSyncInfo(void) const3321 	SyncInfo getInSyncInfo (void) const
3322 	{
3323 		const SyncInfo syncInfo =
3324 		{
3325 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
3326 			VK_ACCESS_2_TRANSFER_READ_BIT_KHR,		// VkAccessFlags			accessMask;
3327 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,	// VkImageLayout			imageLayout;
3328 		};
3329 		return syncInfo;
3330 	}
3331 
getOutSyncInfo(void) const3332 	SyncInfo getOutSyncInfo (void) const
3333 	{
3334 		const SyncInfo syncInfo =
3335 		{
3336 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
3337 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,		// VkAccessFlags			accessMask;
3338 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			imageLayout;
3339 		};
3340 		return syncInfo;
3341 	}
3342 
getData(void) const3343 	Data getData (void) const
3344 	{
3345 		Data data = { 0, DE_NULL };
3346 		return data;
3347 	}
3348 
setData(const Data &)3349 	void setData (const Data&)
3350 	{
3351 		DE_ASSERT(0);
3352 	}
3353 
3354 private:
3355 	OperationContext&		m_context;
3356 	Resource&				m_inResource;
3357 	Resource&				m_outResource;
3358 };
3359 
3360 class CopySupport : public OperationSupport
3361 {
3362 public:
CopySupport(const ResourceDescription & resourceDesc)3363 	CopySupport (const ResourceDescription& resourceDesc)
3364 		: m_resourceType		(resourceDesc.type)
3365 		, m_requiredQueueFlags	(resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
3366 	{
3367 	}
3368 
getInResourceUsageFlags(void) const3369 	deUint32 getInResourceUsageFlags (void) const
3370 	{
3371 		if (m_resourceType == RESOURCE_TYPE_IMAGE)
3372 			return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3373 		else
3374 			return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
3375 	}
3376 
getOutResourceUsageFlags(void) const3377 	deUint32 getOutResourceUsageFlags (void) const
3378 	{
3379 		if (m_resourceType == RESOURCE_TYPE_IMAGE)
3380 			return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3381 		else
3382 			return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3383 	}
3384 
getQueueFlags(const OperationContext & context) const3385 	VkQueueFlags getQueueFlags (const OperationContext& context) const
3386 	{
3387 		DE_UNREF(context);
3388 		return m_requiredQueueFlags;
3389 	}
3390 
build(OperationContext &,Resource &) const3391 	de::MovePtr<Operation> build (OperationContext&, Resource&) const
3392 	{
3393 		DE_ASSERT(0);
3394 		return de::MovePtr<Operation>();
3395 	}
3396 
build(OperationContext & context,Resource & inResource,Resource & outResource) const3397 	de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
3398 	{
3399 		return de::MovePtr<Operation>(new CopyImplementation(context, inResource, outResource));
3400 	}
3401 
3402 private:
3403 	const enum ResourceType		m_resourceType;
3404 	const VkQueueFlags			m_requiredQueueFlags;
3405 };
3406 
3407 } // CopyBufferToImage ns
3408 
3409 namespace CopyImageToBuffer
3410 {
3411 
3412 class WriteImplementation : public Operation
3413 {
3414 public:
WriteImplementation(OperationContext & context,Resource & resource)3415 	WriteImplementation (OperationContext& context, Resource& resource)
3416 		: m_context				(context)
3417 		, m_resource			(resource)
3418 		, m_subresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
3419 		, m_subresourceLayers	(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
3420 	{
3421 		DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_BUFFER);
3422 
3423 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
3424 		const VkDevice			device		= m_context.getDevice();
3425 		Allocator&				allocator	= m_context.getAllocator();
3426 		const VkFormat			format		= VK_FORMAT_R8G8B8A8_UNORM;
3427 		const deUint32			pixelSize	= tcu::getPixelSize(mapVkFormat(format));
3428 
3429 		DE_ASSERT((m_resource.getBuffer().size % pixelSize) == 0);
3430 		m_imageExtent = get2DImageExtentWithSize(m_resource.getBuffer().size, pixelSize);
3431 
3432 		// Source data staging buffer
3433 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3434 			vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible));
3435 
3436 		const Allocation& alloc = m_hostBuffer->getAllocation();
3437 		fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
3438 		flushAlloc(vk, device, alloc);
3439 
3440 		// Source data image
3441 		m_image = de::MovePtr<Image>(new Image(
3442 			vk, device, allocator,
3443 			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
3444 								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
3445 			MemoryRequirement::Any));
3446 	}
3447 
recordCommands(const VkCommandBuffer cmdBuffer)3448 	void recordCommands (const VkCommandBuffer cmdBuffer)
3449 	{
3450 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
3451 		const VkBufferImageCopy		copyRegion				= makeBufferImageCopy(m_imageExtent, m_subresourceLayers);
3452 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3453 
3454 		// Host buffer -> Image
3455 		{
3456 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3457 				VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,		// VkPipelineStageFlags2KHR			srcStageMask
3458 				(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
3459 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
3460 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
3461 				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
3462 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					newLayout
3463 				**m_image,										// VkImage							image
3464 				m_subresourceRange								// VkImageSubresourceRange			subresourceRange
3465 			);
3466 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3467 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3468 
3469 			vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
3470 		}
3471 		// Image -> Resource
3472 		{
3473 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3474 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			srcStageMask
3475 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				srcAccessMask
3476 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
3477 				VK_ACCESS_2_TRANSFER_READ_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
3478 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					oldLayout
3479 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout					newLayout
3480 				**m_image,										// VkImage							image
3481 				m_subresourceRange								// VkImageSubresourceRange			subresourceRange
3482 			);
3483 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3484 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3485 
3486 			vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getBuffer().handle, 1u, &copyRegion);
3487 		}
3488 	}
3489 
getInSyncInfo(void) const3490 	SyncInfo getInSyncInfo (void) const
3491 	{
3492 		return emptySyncInfo;
3493 	}
3494 
getOutSyncInfo(void) const3495 	SyncInfo getOutSyncInfo (void) const
3496 	{
3497 		const SyncInfo syncInfo =
3498 		{
3499 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,		// VkPipelineStageFlags		stageMask;
3500 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,			// VkAccessFlags			accessMask;
3501 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			imageLayout;
3502 		};
3503 		return syncInfo;
3504 	}
3505 
getData(void) const3506 	Data getData (void) const
3507 	{
3508 		return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
3509 	}
3510 
setData(const Data & data)3511 	void setData (const Data& data)
3512 	{
3513 		setHostBufferData(m_context, *m_hostBuffer, data);
3514 	}
3515 
3516 private:
3517 	OperationContext&				m_context;
3518 	Resource&						m_resource;
3519 	const VkImageSubresourceRange	m_subresourceRange;
3520 	const VkImageSubresourceLayers	m_subresourceLayers;
3521 	de::MovePtr<Buffer>				m_hostBuffer;
3522 	de::MovePtr<Image>				m_image;
3523 	VkExtent3D						m_imageExtent;
3524 };
3525 
3526 class ReadImplementation : public Operation
3527 {
3528 public:
ReadImplementation(OperationContext & context,Resource & resource)3529 	ReadImplementation (OperationContext& context, Resource& resource)
3530 		: m_context		(context)
3531 		, m_resource	(resource)
3532 		, m_bufferSize	(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
3533 	{
3534 		DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_IMAGE);
3535 
3536 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
3537 		const VkDevice			device		= m_context.getDevice();
3538 		Allocator&				allocator	= m_context.getAllocator();
3539 
3540 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3541 			vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
3542 
3543 		const Allocation& alloc = m_hostBuffer->getAllocation();
3544 		deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_bufferSize));
3545 		flushAlloc(vk, device, alloc);
3546 	}
3547 
recordCommands(const VkCommandBuffer cmdBuffer)3548 	void recordCommands (const VkCommandBuffer cmdBuffer)
3549 	{
3550 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
3551 		const VkBufferImageCopy		copyRegion				= makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
3552 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3553 
3554 		vk.cmdCopyImageToBuffer(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &copyRegion);
3555 
3556 		// Insert a barrier so data written by the transfer is available to the host
3557 		{
3558 			const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3559 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			srcStageMask
3560 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				srcAccessMask
3561 				VK_PIPELINE_STAGE_2_HOST_BIT_KHR,				// VkPipelineStageFlags2KHR			dstStageMask
3562 				VK_ACCESS_2_HOST_READ_BIT_KHR,					// VkAccessFlags2KHR				dstAccessMask
3563 				**m_hostBuffer,									// VkBuffer							buffer
3564 				0u,												// VkDeviceSize						offset
3565 				VK_WHOLE_SIZE									// VkDeviceSize						size
3566 			);
3567 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
3568 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3569 		}
3570 	}
3571 
getInSyncInfo(void) const3572 	SyncInfo getInSyncInfo (void) const
3573 	{
3574 		const SyncInfo syncInfo =
3575 		{
3576 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
3577 			VK_ACCESS_2_TRANSFER_READ_BIT_KHR,		// VkAccessFlags			accessMask;
3578 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,	// VkImageLayout			imageLayout;
3579 		};
3580 		return syncInfo;
3581 	}
3582 
getOutSyncInfo(void) const3583 	SyncInfo getOutSyncInfo (void) const
3584 	{
3585 		return emptySyncInfo;
3586 	}
3587 
getData(void) const3588 	Data getData (void) const
3589 	{
3590 		return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
3591 	}
3592 
setData(const Data &)3593 	void setData (const Data&)
3594 	{
3595 		DE_ASSERT(0);
3596 	}
3597 
3598 private:
3599 	OperationContext&		m_context;
3600 	Resource&				m_resource;
3601 	de::MovePtr<Buffer>		m_hostBuffer;
3602 	const VkDeviceSize		m_bufferSize;
3603 };
3604 
3605 class CopyImplementation : public Operation
3606 {
3607 public:
CopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)3608 	CopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
3609 		: m_context				(context)
3610 		, m_inResource			(inResource)
3611 		, m_outResource			(outResource)
3612 		, m_subresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
3613 		, m_subresourceLayers	(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
3614 	{
3615 		DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_IMAGE);
3616 		DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_BUFFER);
3617 	}
3618 
recordCommands(const VkCommandBuffer cmdBuffer)3619 	void recordCommands (const VkCommandBuffer cmdBuffer)
3620 	{
3621 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
3622 		const VkBufferImageCopy		copyRegion				= makeBufferImageCopy(m_inResource.getImage().extent, m_subresourceLayers);
3623 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3624 
3625 		{
3626 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3627 				VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,		// VkPipelineStageFlags2KHR			srcStageMask
3628 				(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
3629 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
3630 				VK_ACCESS_2_TRANSFER_READ_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
3631 				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
3632 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					newLayout
3633 				m_inResource.getImage().handle,					// VkImage							image
3634 				m_inResource.getImage().subresourceRange		// VkImageSubresourceRange			subresourceRange
3635 			);
3636 			const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3637 				VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,		// VkPipelineStageFlags2KHR			srcStageMask
3638 				(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
3639 				VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
3640 				VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
3641 				m_outResource.getBuffer().handle,				// VkBuffer							buffer
3642 				0u,												// VkDeviceSize						offset
3643 				m_outResource.getBuffer().size					// VkDeviceSize						size
3644 			);
3645 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2, &imageMemoryBarrier2);
3646 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3647 		}
3648 
3649 		vk.cmdCopyImageToBuffer(cmdBuffer, m_inResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_outResource.getBuffer().handle, 1u, &copyRegion);
3650 	}
3651 
getInSyncInfo(void) const3652 	SyncInfo getInSyncInfo (void) const
3653 	{
3654 		const SyncInfo syncInfo =
3655 		{
3656 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
3657 			VK_ACCESS_2_TRANSFER_READ_BIT_KHR,		// VkAccessFlags			accessMask;
3658 			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			imageLayout;
3659 		};
3660 		return syncInfo;
3661 	}
3662 
getOutSyncInfo(void) const3663 	SyncInfo getOutSyncInfo (void) const
3664 	{
3665 		const SyncInfo syncInfo =
3666 		{
3667 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
3668 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,		// VkAccessFlags			accessMask;
3669 			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			imageLayout;
3670 		};
3671 		return syncInfo;
3672 	}
3673 
getData(void) const3674 	Data getData (void) const
3675 	{
3676 		Data data = { 0, DE_NULL };
3677 		return data;
3678 	}
3679 
setData(const Data &)3680 	void setData (const Data&)
3681 	{
3682 		DE_ASSERT(0);
3683 	}
3684 
3685 private:
3686 	OperationContext&				m_context;
3687 	Resource&						m_inResource;
3688 	Resource&						m_outResource;
3689 	const VkImageSubresourceRange	m_subresourceRange;
3690 	const VkImageSubresourceLayers	m_subresourceLayers;
3691 };
3692 
3693 class Support : public OperationSupport
3694 {
3695 public:
Support(const ResourceDescription & resourceDesc,const AccessMode mode)3696 	Support (const ResourceDescription& resourceDesc, const AccessMode mode)
3697 		: m_mode				(mode)
3698 		, m_requiredQueueFlags	(resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
3699 	{
3700 		DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
3701 		DE_ASSERT(m_mode == ACCESS_MODE_READ || resourceDesc.type != RESOURCE_TYPE_IMAGE);
3702 		DE_ASSERT(m_mode == ACCESS_MODE_WRITE || resourceDesc.type != RESOURCE_TYPE_BUFFER);
3703 	}
3704 
getInResourceUsageFlags(void) const3705 	deUint32 getInResourceUsageFlags (void) const
3706 	{
3707 		return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0;
3708 	}
3709 
getOutResourceUsageFlags(void) const3710 	deUint32 getOutResourceUsageFlags (void) const
3711 	{
3712 		return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0;
3713 	}
3714 
getQueueFlags(const OperationContext & context) const3715 	VkQueueFlags getQueueFlags (const OperationContext& context) const
3716 	{
3717 		DE_UNREF(context);
3718 		return m_requiredQueueFlags;
3719 	}
3720 
build(OperationContext & context,Resource & resource) const3721 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3722 	{
3723 		if (m_mode == ACCESS_MODE_READ)
3724 			return de::MovePtr<Operation>(new ReadImplementation(context, resource));
3725 		else
3726 			return de::MovePtr<Operation>(new WriteImplementation(context, resource));
3727 	}
3728 
build(OperationContext &,Resource &,Resource &) const3729 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3730 	{
3731 		DE_ASSERT(0);
3732 		return de::MovePtr<Operation>();
3733 	}
3734 
3735 private:
3736 	const AccessMode			m_mode;
3737 	const VkQueueFlags			m_requiredQueueFlags;
3738 };
3739 
3740 } // CopyImageToBuffer ns
3741 
3742 namespace ClearImage
3743 {
3744 
3745 enum ClearMode
3746 {
3747 	CLEAR_MODE_COLOR,
3748 	CLEAR_MODE_DEPTH_STENCIL,
3749 };
3750 
3751 class Implementation : public Operation
3752 {
3753 public:
Implementation(OperationContext & context,Resource & resource,const ClearMode mode)3754 	Implementation (OperationContext& context, Resource& resource, const ClearMode mode)
3755 		: m_context		(context)
3756 		, m_resource	(resource)
3757 		, m_clearValue	(makeClearValue(m_resource.getImage().format))
3758 		, m_mode		(mode)
3759 	{
3760 		const VkDeviceSize			size		= getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent);
3761 		const VkExtent3D&			extent		= m_resource.getImage().extent;
3762 		const VkFormat				format		= m_resource.getImage().format;
3763 		const tcu::TextureFormat	texFormat	= mapVkFormat(format);
3764 
3765 		m_data.resize(static_cast<std::size_t>(size));
3766 		tcu::PixelBufferAccess imagePixels(texFormat, extent.width, extent.height, extent.depth, &m_data[0]);
3767 		clearPixelBuffer(imagePixels, m_clearValue);
3768 	}
3769 
recordCommands(const VkCommandBuffer cmdBuffer)3770 	void recordCommands (const VkCommandBuffer cmdBuffer)
3771 	{
3772 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
3773 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3774 
3775 		VkPipelineStageFlags2KHR dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
3776 		if (m_context.getSynchronizationType() == SynchronizationType::SYNCHRONIZATION2)
3777 			dstStageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR;
3778 
3779 		const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3780 			VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,		// VkPipelineStageFlags2KHR			srcStageMask
3781 			(VkAccessFlags)0,								// VkAccessFlags2KHR				srcAccessMask
3782 			dstStageMask,									// VkPipelineStageFlags2KHR			dstStageMask
3783 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
3784 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout					oldLayout
3785 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout					newLayout
3786 			m_resource.getImage().handle,					// VkImage							image
3787 			m_resource.getImage().subresourceRange			// VkImageSubresourceRange			subresourceRange
3788 		);
3789 		VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3790 		synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3791 
3792 		if (m_mode == CLEAR_MODE_COLOR)
3793 			vk.cmdClearColorImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_clearValue.color, 1u, &m_resource.getImage().subresourceRange);
3794 		else
3795 			vk.cmdClearDepthStencilImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_clearValue.depthStencil, 1u, &m_resource.getImage().subresourceRange);
3796 	}
3797 
getInSyncInfo(void) const3798 	SyncInfo getInSyncInfo (void) const
3799 	{
3800 		return emptySyncInfo;
3801 	}
3802 
getOutSyncInfo(void) const3803 	SyncInfo getOutSyncInfo (void) const
3804 	{
3805 		VkPipelineStageFlags2KHR stageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
3806 		if (m_context.getSynchronizationType() == SynchronizationType::SYNCHRONIZATION2)
3807 			stageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR;
3808 
3809 		return
3810 		{
3811 			stageMask,								// VkPipelineStageFlags		stageMask;
3812 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,		// VkAccessFlags			accessMask;
3813 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			imageLayout;
3814 		};
3815 	}
3816 
getData(void) const3817 	Data getData (void) const
3818 	{
3819 		const Data data =
3820 		{
3821 			m_data.size(),		// std::size_t		size;
3822 			&m_data[0],			// const deUint8*	data;
3823 		};
3824 		return data;
3825 	}
3826 
setData(const Data &)3827 	void setData (const Data&)
3828 	{
3829 		DE_ASSERT(0);
3830 	}
3831 
3832 private:
3833 	OperationContext&		m_context;
3834 	Resource&				m_resource;
3835 	std::vector<deUint8>	m_data;
3836 	const VkClearValue		m_clearValue;
3837 	const ClearMode			m_mode;
3838 };
3839 
3840 class Support : public OperationSupport
3841 {
3842 public:
Support(const ResourceDescription & resourceDesc,const ClearMode mode)3843 	Support (const ResourceDescription& resourceDesc, const ClearMode mode)
3844 		: m_resourceDesc	(resourceDesc)
3845 		, m_mode			(mode)
3846 	{
3847 		DE_ASSERT(m_mode == CLEAR_MODE_COLOR || m_mode == CLEAR_MODE_DEPTH_STENCIL);
3848 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
3849 		DE_ASSERT(m_resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT || (m_mode != CLEAR_MODE_COLOR));
3850 		DE_ASSERT((m_resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) || (m_mode != CLEAR_MODE_DEPTH_STENCIL));
3851 	}
3852 
getInResourceUsageFlags(void) const3853 	deUint32 getInResourceUsageFlags (void) const
3854 	{
3855 		return 0;
3856 	}
3857 
getOutResourceUsageFlags(void) const3858 	deUint32 getOutResourceUsageFlags (void) const
3859 	{
3860 		return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3861 	}
3862 
getQueueFlags(const OperationContext & context) const3863 	VkQueueFlags getQueueFlags (const OperationContext& context) const
3864 	{
3865 		DE_UNREF(context);
3866 		if (m_mode == CLEAR_MODE_COLOR)
3867 			return VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
3868 		else
3869 			return VK_QUEUE_GRAPHICS_BIT;
3870 	}
3871 
build(OperationContext & context,Resource & resource) const3872 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3873 	{
3874 		return de::MovePtr<Operation>(new Implementation(context, resource, m_mode));
3875 	}
3876 
build(OperationContext &,Resource &,Resource &) const3877 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3878 	{
3879 		DE_ASSERT(0);
3880 		return de::MovePtr<Operation>();
3881 	}
3882 
3883 private:
3884 	const ResourceDescription	m_resourceDesc;
3885 	const ClearMode				m_mode;
3886 };
3887 
3888 } // ClearImage ns
3889 
3890 namespace Draw
3891 {
3892 
3893 enum DrawCall
3894 {
3895 	DRAW_CALL_DRAW,
3896 	DRAW_CALL_DRAW_INDEXED,
3897 	DRAW_CALL_DRAW_INDIRECT,
3898 	DRAW_CALL_DRAW_INDEXED_INDIRECT,
3899 };
3900 
3901 //! A write operation that is a result of drawing to an image.
3902 //! \todo Add support for depth/stencil too?
3903 class Implementation : public Operation
3904 {
3905 public:
Implementation(OperationContext & context,Resource & resource,const DrawCall drawCall)3906 	Implementation (OperationContext& context, Resource& resource, const DrawCall drawCall)
3907 		: m_context		(context)
3908 		, m_resource	(resource)
3909 		, m_drawCall	(drawCall)
3910 		, m_vertices	(context)
3911 	{
3912 		const DeviceInterface&		vk				= context.getDeviceInterface();
3913 		const VkDevice				device			= context.getDevice();
3914 		Allocator&					allocator		= context.getAllocator();
3915 
3916 		// Indirect buffer
3917 
3918 		if (m_drawCall == DRAW_CALL_DRAW_INDIRECT)
3919 		{
3920 			m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
3921 				makeBufferCreateInfo(sizeof(VkDrawIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
3922 
3923 			const Allocation&				alloc				= m_indirectBuffer->getAllocation();
3924 			VkDrawIndirectCommand* const	pIndirectCommand	= static_cast<VkDrawIndirectCommand*>(alloc.getHostPtr());
3925 
3926 			pIndirectCommand->vertexCount	= m_vertices.getNumVertices();
3927 			pIndirectCommand->instanceCount	= 1u;
3928 			pIndirectCommand->firstVertex	= 0u;
3929 			pIndirectCommand->firstInstance	= 0u;
3930 
3931 			flushAlloc(vk, device, alloc);
3932 		}
3933 		else if (m_drawCall == DRAW_CALL_DRAW_INDEXED_INDIRECT)
3934 		{
3935 			m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
3936 				makeBufferCreateInfo(sizeof(VkDrawIndexedIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
3937 
3938 			const Allocation&					alloc				= m_indirectBuffer->getAllocation();
3939 			VkDrawIndexedIndirectCommand* const	pIndirectCommand	= static_cast<VkDrawIndexedIndirectCommand*>(alloc.getHostPtr());
3940 
3941 			pIndirectCommand->indexCount	= m_vertices.getNumIndices();
3942 			pIndirectCommand->instanceCount	= 1u;
3943 			pIndirectCommand->firstIndex	= 0u;
3944 			pIndirectCommand->vertexOffset	= 0u;
3945 			pIndirectCommand->firstInstance	= 0u;
3946 
3947 			flushAlloc(vk, device, alloc);
3948 		}
3949 
3950 		// Resource image is the color attachment
3951 
3952 		m_colorFormat			= m_resource.getImage().format;
3953 		m_colorSubresourceRange	= m_resource.getImage().subresourceRange;
3954 		m_colorImage			= m_resource.getImage().handle;
3955 		m_attachmentExtent		= m_resource.getImage().extent;
3956 
3957 		// Pipeline
3958 
3959 		m_colorAttachmentView	= makeImageView		(vk, device, m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
3960 		m_renderPass			= makeRenderPass	(vk, device, m_colorFormat);
3961 		m_framebuffer			= makeFramebuffer	(vk, device, *m_renderPass, *m_colorAttachmentView, m_attachmentExtent.width, m_attachmentExtent.height);
3962 		m_pipelineLayout		= makePipelineLayout(vk, device);
3963 
3964 		GraphicsPipelineBuilder pipelineBuilder;
3965 		pipelineBuilder
3966 			.setRenderSize					(tcu::IVec2(m_attachmentExtent.width, m_attachmentExtent.height))
3967 			.setVertexInputSingleAttribute	(m_vertices.getVertexFormat(), m_vertices.getVertexStride())
3968 			.setShader						(vk, device, VK_SHADER_STAGE_VERTEX_BIT,	context.getBinaryCollection().get("draw_vert"), DE_NULL)
3969 			.setShader						(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,	context.getBinaryCollection().get("draw_frag"), DE_NULL);
3970 
3971 		m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData(), context.getResourceInterface() );
3972 
3973 		// Set expected draw values
3974 
3975 		m_expectedData.resize(static_cast<size_t>(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent)));
3976 		tcu::PixelBufferAccess imagePixels(mapVkFormat(m_colorFormat), m_attachmentExtent.width, m_attachmentExtent.height, m_attachmentExtent.depth, &m_expectedData[0]);
3977 		clearPixelBuffer(imagePixels, makeClearValue(m_colorFormat));
3978 	}
3979 
recordCommands(const VkCommandBuffer cmdBuffer)3980 	void recordCommands (const VkCommandBuffer cmdBuffer)
3981 	{
3982 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
3983 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3984 
3985 		// Change color attachment image layout
3986 		{
3987 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3988 				VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,				// VkPipelineStageFlags2KHR			srcStageMask
3989 				(VkAccessFlags)0,										// VkAccessFlags2KHR				srcAccessMask
3990 				VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,	// VkPipelineStageFlags2KHR			dstStageMask
3991 				VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
3992 				VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout					oldLayout
3993 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout					newLayout
3994 				m_colorImage,											// VkImage							image
3995 				m_colorSubresourceRange									// VkImageSubresourceRange			subresourceRange
3996 			);
3997 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3998 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3999 		}
4000 
4001 		{
4002 			const VkRect2D	renderArea	= makeRect2D(m_attachmentExtent);
4003 			const tcu::Vec4	clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
4004 
4005 			beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
4006 		}
4007 
4008 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4009 		{
4010 			const VkDeviceSize	vertexBufferOffset	= 0ull;
4011 			const VkBuffer		vertexBuffer		= m_vertices.getVertexBuffer();
4012 			vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
4013 		}
4014 
4015 		if (m_drawCall == DRAW_CALL_DRAW_INDEXED || m_drawCall == DRAW_CALL_DRAW_INDEXED_INDIRECT)
4016 			vk.cmdBindIndexBuffer(cmdBuffer, m_vertices.getIndexBuffer(), 0u, m_vertices.getIndexType());
4017 
4018 		switch (m_drawCall)
4019 		{
4020 			case DRAW_CALL_DRAW:
4021 				vk.cmdDraw(cmdBuffer, m_vertices.getNumVertices(), 1u, 0u, 0u);
4022 				break;
4023 
4024 			case DRAW_CALL_DRAW_INDEXED:
4025 				vk.cmdDrawIndexed(cmdBuffer, m_vertices.getNumIndices(), 1u, 0u, 0, 0u);
4026 				break;
4027 
4028 			case DRAW_CALL_DRAW_INDIRECT:
4029 				vk.cmdDrawIndirect(cmdBuffer, **m_indirectBuffer, 0u, 1u, 0u);
4030 				break;
4031 
4032 			case DRAW_CALL_DRAW_INDEXED_INDIRECT:
4033 				vk.cmdDrawIndexedIndirect(cmdBuffer, **m_indirectBuffer, 0u, 1u, 0u);
4034 				break;
4035 		}
4036 
4037 		endRenderPass(vk, cmdBuffer);
4038 	}
4039 
getInSyncInfo(void) const4040 	SyncInfo getInSyncInfo (void) const
4041 	{
4042 		return emptySyncInfo;
4043 	}
4044 
getOutSyncInfo(void) const4045 	SyncInfo getOutSyncInfo (void) const
4046 	{
4047 		const SyncInfo syncInfo =
4048 		{
4049 			VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,	// VkPipelineStageFlags		stageMask;
4050 			VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,				// VkAccessFlags			accessMask;
4051 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			imageLayout;
4052 		};
4053 		return syncInfo;
4054 	}
4055 
getData(void) const4056 	Data getData (void) const
4057 	{
4058 		const Data data =
4059 		{
4060 			m_expectedData.size(),		// std::size_t		size;
4061 			&m_expectedData[0],			// const deUint8*	data;
4062 		};
4063 		return data;
4064 	}
4065 
setData(const Data & data)4066 	void setData (const Data& data)
4067 	{
4068 		DE_ASSERT(m_expectedData.size() == data.size);
4069 		deMemcpy(&m_expectedData[0], data.data, data.size);
4070 	}
4071 
4072 private:
4073 	OperationContext&			m_context;
4074 	Resource&					m_resource;
4075 	const DrawCall				m_drawCall;
4076 	const VertexGrid			m_vertices;
4077 	std::vector<deUint8>		m_expectedData;
4078 	de::MovePtr<Buffer>			m_indirectBuffer;
4079 	VkFormat					m_colorFormat;
4080 	VkImage						m_colorImage;
4081 	Move<VkImageView>			m_colorAttachmentView;
4082 	VkImageSubresourceRange		m_colorSubresourceRange;
4083 	VkExtent3D					m_attachmentExtent;
4084 	Move<VkRenderPass>			m_renderPass;
4085 	Move<VkFramebuffer>			m_framebuffer;
4086 	Move<VkPipelineLayout>		m_pipelineLayout;
4087 	Move<VkPipeline>			m_pipeline;
4088 };
4089 
4090 template<typename T, std::size_t N>
toString(const T (& values)[N])4091 std::string toString (const T (&values)[N])
4092 {
4093 	std::ostringstream str;
4094 	for (std::size_t i = 0; i < N; ++i)
4095 		str << (i != 0 ? ", " : "") << values[i];
4096 	return str.str();
4097 }
4098 
4099 class Support : public OperationSupport
4100 {
4101 public:
Support(const ResourceDescription & resourceDesc,const DrawCall drawCall)4102 	Support (const ResourceDescription& resourceDesc, const DrawCall drawCall)
4103 		: m_resourceDesc	(resourceDesc)
4104 		, m_drawCall		(drawCall)
4105 	{
4106 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE && m_resourceDesc.imageType == VK_IMAGE_TYPE_2D);
4107 		DE_ASSERT(!isDepthStencilFormat(m_resourceDesc.imageFormat));
4108 	}
4109 
initPrograms(SourceCollections & programCollection) const4110 	void initPrograms (SourceCollections& programCollection) const
4111 	{
4112 		// Vertex
4113 		{
4114 			std::ostringstream src;
4115 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4116 				<< "\n"
4117 				<< "layout(location = 0) in vec4 v_in_position;\n"
4118 				<< "\n"
4119 				<< "out " << s_perVertexBlock << ";\n"
4120 				<< "\n"
4121 				<< "void main (void)\n"
4122 				<< "{\n"
4123 				<< "    gl_Position = v_in_position;\n"
4124 				<< "}\n";
4125 
4126 			programCollection.glslSources.add("draw_vert") << glu::VertexSource(src.str());
4127 		}
4128 
4129 		// Fragment
4130 		{
4131 			const VkClearValue	clearValue		= makeClearValue(m_resourceDesc.imageFormat);
4132 			const bool			isIntegerFormat = isIntFormat(m_resourceDesc.imageFormat) || isUintFormat(m_resourceDesc.imageFormat);
4133 			const std::string	colorType		= (isIntegerFormat ? "uvec4" : "vec4");
4134 
4135 			std::ostringstream src;
4136 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4137 				<< "\n"
4138 				<< "layout(location = 0) out " << colorType << " o_color;\n"
4139 				<< "\n"
4140 				<< "void main (void)\n"
4141 				<< "{\n"
4142 				<< "    o_color = " << colorType << "(" << (isIntegerFormat ? toString(clearValue.color.uint32) : toString(clearValue.color.float32)) << ");\n"
4143 				<< "}\n";
4144 
4145 			programCollection.glslSources.add("draw_frag") << glu::FragmentSource(src.str());
4146 		}
4147 	}
4148 
getInResourceUsageFlags(void) const4149 	deUint32 getInResourceUsageFlags (void) const
4150 	{
4151 		return 0;
4152 	}
4153 
getOutResourceUsageFlags(void) const4154 	deUint32 getOutResourceUsageFlags (void) const
4155 	{
4156 		return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4157 	}
4158 
getQueueFlags(const OperationContext & context) const4159 	VkQueueFlags getQueueFlags (const OperationContext& context) const
4160 	{
4161 		DE_UNREF(context);
4162 		return VK_QUEUE_GRAPHICS_BIT;
4163 	}
4164 
build(OperationContext & context,Resource & resource) const4165 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4166 	{
4167 		return de::MovePtr<Operation>(new Implementation(context, resource, m_drawCall));
4168 	}
4169 
build(OperationContext &,Resource &,Resource &) const4170 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4171 	{
4172 		DE_ASSERT(0);
4173 		return de::MovePtr<Operation>();
4174 	}
4175 
4176 private:
4177 	const ResourceDescription	m_resourceDesc;
4178 	const DrawCall				m_drawCall;
4179 };
4180 
4181 } // Draw ns
4182 
4183 namespace ClearAttachments
4184 {
4185 
4186 class Implementation : public Operation
4187 {
4188 public:
Implementation(OperationContext & context,Resource & resource)4189 	Implementation (OperationContext& context, Resource& resource)
4190 		: m_context		(context)
4191 		, m_resource	(resource)
4192 		, m_clearValue	(makeClearValue(m_resource.getImage().format))
4193 	{
4194 		const DeviceInterface&		vk				= context.getDeviceInterface();
4195 		const VkDevice				device			= context.getDevice();
4196 
4197 		const VkDeviceSize			size		= getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent);
4198 		const VkExtent3D&			extent		= m_resource.getImage().extent;
4199 		const VkFormat				format		= m_resource.getImage().format;
4200 		const tcu::TextureFormat	texFormat	= mapVkFormat(format);
4201 		const SyncInfo				syncInfo	= getOutSyncInfo();
4202 
4203 		m_data.resize(static_cast<std::size_t>(size));
4204 		tcu::PixelBufferAccess imagePixels(texFormat, extent.width, extent.height, extent.depth, &m_data[0]);
4205 		clearPixelBuffer(imagePixels, m_clearValue);
4206 
4207 		m_attachmentView = makeImageView(vk, device, m_resource.getImage().handle, getImageViewType(m_resource.getImage().imageType), m_resource.getImage().format, m_resource.getImage().subresourceRange);
4208 
4209 		switch (m_resource.getImage().subresourceRange.aspectMask)
4210 		{
4211 			case VK_IMAGE_ASPECT_COLOR_BIT:
4212 				m_renderPass = makeRenderPass(vk, device, m_resource.getImage().format, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_DONT_CARE, syncInfo.imageLayout);
4213 			break;
4214 			case VK_IMAGE_ASPECT_STENCIL_BIT:
4215 			case VK_IMAGE_ASPECT_DEPTH_BIT:
4216 				m_renderPass = makeRenderPass(vk, device, VK_FORMAT_UNDEFINED, m_resource.getImage().format, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, syncInfo.imageLayout);
4217 			break;
4218 			default:
4219 				DE_ASSERT(0);
4220 			break;
4221 		}
4222 
4223 		m_frameBuffer	= makeFramebuffer(vk, device, *m_renderPass, *m_attachmentView, m_resource.getImage().extent.width, m_resource.getImage().extent.height);
4224 	}
4225 
recordCommands(const VkCommandBuffer cmdBuffer)4226 	void recordCommands (const VkCommandBuffer cmdBuffer)
4227 	{
4228 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
4229 		if ((m_resource.getImage().subresourceRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0)
4230 		{
4231 			const VkImageMemoryBarrier imageBarrier =
4232 			{
4233 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// sType
4234 				DE_NULL,											// pNext
4235 				0u,													// srcAccessMask
4236 				VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// dstAccessMask
4237 				VK_IMAGE_LAYOUT_UNDEFINED,							// oldLayout
4238 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// newLayout
4239 				VK_QUEUE_FAMILY_IGNORED,							// srcQueueFamilyIndex
4240 				VK_QUEUE_FAMILY_IGNORED,							// dstQueueFamilyIndex
4241 				m_resource.getImage().handle,						// image
4242 				m_resource.getImage().subresourceRange				// subresourceRange
4243 			};
4244 			vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
4245 		}
4246 		beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_frameBuffer, makeRect2D(0 ,0, m_resource.getImage().extent.width, m_resource.getImage().extent.height), m_clearValue);
4247 
4248 		const VkClearAttachment	clearAttachment	=
4249 		{
4250 			m_resource.getImage().subresourceRange.aspectMask,	// VkImageAspectFlags	aspectMask;
4251 			0,													// deUint32				colorAttachment;
4252 			m_clearValue										// VkClearValue			clearValue;
4253 		};
4254 
4255 		const VkRect2D			rect2D			= makeRect2D(m_resource.getImage().extent);
4256 
4257 		const VkClearRect		clearRect		=
4258 		{
4259 			rect2D,												// VkRect2D	rect;
4260 			0u,													// deUint32	baseArrayLayer;
4261 			m_resource.getImage().subresourceLayers.layerCount	// deUint32	layerCount;
4262 		};
4263 
4264 		vk.cmdClearAttachments(cmdBuffer, 1, &clearAttachment, 1, &clearRect);
4265 
4266 		endRenderPass(vk, cmdBuffer);
4267 	}
4268 
getInSyncInfo(void) const4269 	SyncInfo getInSyncInfo (void) const
4270 	{
4271 		return emptySyncInfo;
4272 	}
4273 
getOutSyncInfo(void) const4274 	SyncInfo getOutSyncInfo (void) const
4275 	{
4276 		SyncInfo syncInfo;
4277 		syncInfo.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR;
4278 
4279 		switch (m_resource.getImage().subresourceRange.aspectMask)
4280 		{
4281 			case VK_IMAGE_ASPECT_COLOR_BIT:
4282 				syncInfo.accessMask		= VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR;
4283 				syncInfo.imageLayout	= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4284 			break;
4285 			case VK_IMAGE_ASPECT_STENCIL_BIT:
4286 			case VK_IMAGE_ASPECT_DEPTH_BIT:
4287 				syncInfo.accessMask		= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR;
4288 				syncInfo.imageLayout	= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
4289 			break;
4290 			default:
4291 				DE_ASSERT(0);
4292 			break;
4293 		}
4294 
4295 		return syncInfo;
4296 	}
4297 
getData(void) const4298 	Data getData (void) const
4299 	{
4300 		const Data data =
4301 		{
4302 			m_data.size(),	// std::size_t		size;
4303 			&m_data[0],		// const deUint8*	data;
4304 		};
4305 		return data;
4306 	}
4307 
setData(const Data &)4308 	void setData (const Data&)
4309 	{
4310 		DE_ASSERT(0);
4311 	}
4312 
4313 private:
4314 	OperationContext&		m_context;
4315 	Resource&				m_resource;
4316 	std::vector<deUint8>	m_data;
4317 	const VkClearValue		m_clearValue;
4318 	Move<VkImageView>		m_attachmentView;
4319 	Move<VkRenderPass>		m_renderPass;
4320 	Move<VkFramebuffer>		m_frameBuffer;
4321 };
4322 
4323 class Support : public OperationSupport
4324 {
4325 public:
Support(const ResourceDescription & resourceDesc)4326 	Support (const ResourceDescription& resourceDesc)
4327 		: m_resourceDesc (resourceDesc)
4328 	{
4329 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
4330 	}
4331 
getInResourceUsageFlags(void) const4332 	deUint32 getInResourceUsageFlags (void) const
4333 	{
4334 		return 0;
4335 	}
4336 
getOutResourceUsageFlags(void) const4337 	deUint32 getOutResourceUsageFlags (void) const
4338 	{
4339 		switch (m_resourceDesc.imageAspect)
4340 		{
4341 			case VK_IMAGE_ASPECT_COLOR_BIT:
4342 				return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4343 			case VK_IMAGE_ASPECT_STENCIL_BIT:
4344 			case VK_IMAGE_ASPECT_DEPTH_BIT:
4345 				return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
4346 			default:
4347 				DE_ASSERT(0);
4348 		}
4349 		return 0u;
4350 	}
4351 
getQueueFlags(const OperationContext & context) const4352 	VkQueueFlags getQueueFlags (const OperationContext& context) const
4353 	{
4354 		DE_UNREF(context);
4355 		return VK_QUEUE_GRAPHICS_BIT;
4356 	}
4357 
build(OperationContext & context,Resource & resource) const4358 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4359 	{
4360 		return de::MovePtr<Operation>(new Implementation(context, resource));
4361 	}
4362 
build(OperationContext &,Resource &,Resource &) const4363 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4364 	{
4365 		DE_ASSERT(0);
4366 		return de::MovePtr<Operation>();
4367 	}
4368 
4369 private:
4370 	const ResourceDescription	m_resourceDesc;
4371 };
4372 
4373 } // ClearAttachments
4374 
4375 namespace IndirectBuffer
4376 {
4377 
4378 class GraphicsPipeline : public Pipeline
4379 {
4380 public:
GraphicsPipeline(OperationContext & context,const ResourceType resourceType,const VkBuffer indirectBuffer,const std::string & shaderPrefix,const VkDescriptorSetLayout descriptorSetLayout)4381 	GraphicsPipeline (OperationContext&				context,
4382 					  const ResourceType			resourceType,
4383 					  const VkBuffer				indirectBuffer,
4384 					  const std::string&			shaderPrefix,
4385 					  const VkDescriptorSetLayout	descriptorSetLayout)
4386 		: m_resourceType	(resourceType)
4387 		, m_indirectBuffer	(indirectBuffer)
4388 		, m_vertices		(context)
4389 	{
4390 		const DeviceInterface&		vk				= context.getDeviceInterface();
4391 		const VkDevice				device			= context.getDevice();
4392 		Allocator&					allocator		= context.getAllocator();
4393 
4394 		// Color attachment
4395 
4396 		m_colorFormat					= VK_FORMAT_R8G8B8A8_UNORM;
4397 		m_colorImageSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4398 		m_colorImageExtent				= makeExtent3D(16u, 16u, 1u);
4399 		m_colorAttachmentImage			= de::MovePtr<Image>(new Image(vk, device, allocator,
4400 			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4401 								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
4402 			MemoryRequirement::Any));
4403 
4404 		// Pipeline
4405 
4406 		m_colorAttachmentView	= makeImageView		(vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
4407 		m_renderPass			= makeRenderPass	(vk, device, m_colorFormat);
4408 		m_framebuffer			= makeFramebuffer	(vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height);
4409 		m_pipelineLayout		= makePipelineLayout(vk, device, descriptorSetLayout);
4410 
4411 		GraphicsPipelineBuilder pipelineBuilder;
4412 		pipelineBuilder
4413 			.setRenderSize					(tcu::IVec2(m_colorImageExtent.width, m_colorImageExtent.height))
4414 			.setVertexInputSingleAttribute	(m_vertices.getVertexFormat(), m_vertices.getVertexStride())
4415 			.setShader						(vk, device, VK_SHADER_STAGE_VERTEX_BIT,	context.getBinaryCollection().get(shaderPrefix + "vert"), DE_NULL)
4416 			.setShader						(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,	context.getBinaryCollection().get(shaderPrefix + "frag"), DE_NULL);
4417 
4418 		m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData(), context.getResourceInterface());
4419 	}
4420 
recordCommands(OperationContext & context,const VkCommandBuffer cmdBuffer,const VkDescriptorSet descriptorSet)4421 	void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
4422 	{
4423 		const DeviceInterface&		vk						= context.getDeviceInterface();
4424 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(context.getSynchronizationType(), vk, DE_FALSE);
4425 
4426 		// Change color attachment image layout
4427 		{
4428 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
4429 				VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,				// VkPipelineStageFlags2KHR			srcStageMask
4430 				(VkAccessFlags)0,										// VkAccessFlags2KHR				srcAccessMask
4431 				VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,	// VkPipelineStageFlags2KHR			dstStageMask
4432 				VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
4433 				VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout					oldLayout
4434 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout					newLayout
4435 				**m_colorAttachmentImage,								// VkImage							image
4436 				m_colorImageSubresourceRange							// VkImageSubresourceRange			subresourceRange
4437 			);
4438 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
4439 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
4440 		}
4441 
4442 		{
4443 			const VkRect2D	renderArea	= makeRect2D(m_colorImageExtent);
4444 			const tcu::Vec4	clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
4445 
4446 			beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
4447 		}
4448 
4449 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4450 		vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
4451 		{
4452 			const VkDeviceSize	vertexBufferOffset	= 0ull;
4453 			const VkBuffer		vertexBuffer		= m_vertices.getVertexBuffer();
4454 			vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
4455 		}
4456 
4457 		switch (m_resourceType)
4458 		{
4459 			case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
4460 				vk.cmdDrawIndirect(cmdBuffer, m_indirectBuffer, 0u, 1u, 0u);
4461 				break;
4462 
4463 			case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
4464 				vk.cmdBindIndexBuffer(cmdBuffer, m_vertices.getIndexBuffer(), 0u, m_vertices.getIndexType());
4465 				vk.cmdDrawIndexedIndirect(cmdBuffer, m_indirectBuffer, 0u, 1u, 0u);
4466 				break;
4467 
4468 			default:
4469 				DE_ASSERT(0);
4470 				break;
4471 		}
4472 		endRenderPass(vk, cmdBuffer);
4473 	}
4474 
4475 private:
4476 	const ResourceType			m_resourceType;
4477 	const VkBuffer				m_indirectBuffer;
4478 	const VertexGrid			m_vertices;
4479 	VkFormat					m_colorFormat;
4480 	de::MovePtr<Image>			m_colorAttachmentImage;
4481 	Move<VkImageView>			m_colorAttachmentView;
4482 	VkExtent3D					m_colorImageExtent;
4483 	VkImageSubresourceRange		m_colorImageSubresourceRange;
4484 	Move<VkRenderPass>			m_renderPass;
4485 	Move<VkFramebuffer>			m_framebuffer;
4486 	Move<VkPipelineLayout>		m_pipelineLayout;
4487 	Move<VkPipeline>			m_pipeline;
4488 };
4489 
4490 class ComputePipeline : public Pipeline
4491 {
4492 public:
ComputePipeline(OperationContext & context,const VkBuffer indirectBuffer,const std::string & shaderPrefix,const VkDescriptorSetLayout descriptorSetLayout)4493 	ComputePipeline (OperationContext&				context,
4494 					 const VkBuffer					indirectBuffer,
4495 					 const std::string&				shaderPrefix,
4496 					 const VkDescriptorSetLayout	descriptorSetLayout)
4497 		: m_indirectBuffer	(indirectBuffer)
4498 	{
4499 		const DeviceInterface&	vk		= context.getDeviceInterface();
4500 		const VkDevice			device	= context.getDevice();
4501 
4502 		const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get(shaderPrefix + "comp"), (VkShaderModuleCreateFlags)0));
4503 
4504 		m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
4505 		m_pipeline		 = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData(), context.getResourceInterface());
4506 	}
4507 
recordCommands(OperationContext & context,const VkCommandBuffer cmdBuffer,const VkDescriptorSet descriptorSet)4508 	void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
4509 	{
4510 		const DeviceInterface&	vk	= context.getDeviceInterface();
4511 
4512 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
4513 		vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
4514 		vk.cmdDispatchIndirect(cmdBuffer, m_indirectBuffer, 0u);
4515 	}
4516 
4517 private:
4518 	const VkBuffer				m_indirectBuffer;
4519 	Move<VkPipelineLayout>		m_pipelineLayout;
4520 	Move<VkPipeline>			m_pipeline;
4521 };
4522 
4523 //! Read indirect buffer by executing an indirect draw or dispatch command.
4524 class ReadImplementation : public Operation
4525 {
4526 public:
ReadImplementation(OperationContext & context,Resource & resource)4527 	ReadImplementation (OperationContext& context, Resource& resource)
4528 		: m_context				(context)
4529 		, m_resource			(resource)
4530 		, m_stage				(resource.getType() == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_VERTEX_BIT)
4531 		, m_pipelineStage		(pipelineStageFlagsFromShaderStageFlagBits(m_stage))
4532 		, m_hostBufferSizeBytes	(sizeof(deUint32))
4533 	{
4534 		requireFeaturesForSSBOAccess (m_context, m_stage);
4535 
4536 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
4537 		const VkDevice			device		= m_context.getDevice();
4538 		Allocator&				allocator	= m_context.getAllocator();
4539 
4540 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
4541 			vk, device, allocator, makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
4542 
4543 		// Init host buffer data
4544 		{
4545 			const Allocation& alloc = m_hostBuffer->getAllocation();
4546 			deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_hostBufferSizeBytes));
4547 			flushAlloc(vk, device, alloc);
4548 		}
4549 
4550 		// Prepare descriptors
4551 		{
4552 			m_descriptorSetLayout = DescriptorSetLayoutBuilder()
4553 				.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
4554 				.build(vk, device);
4555 
4556 			m_descriptorPool = DescriptorPoolBuilder()
4557 				.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4558 				.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4559 
4560 			m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
4561 
4562 			const VkDescriptorBufferInfo  hostBufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_hostBufferSizeBytes);
4563 
4564 			DescriptorSetUpdateBuilder()
4565 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
4566 				.update(vk, device);
4567 		}
4568 
4569 		// Create pipeline
4570 		m_pipeline = (m_resource.getType() == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH
4571 			? de::MovePtr<Pipeline>(new ComputePipeline(context, m_resource.getBuffer().handle, "read_ib_", *m_descriptorSetLayout))
4572 			: de::MovePtr<Pipeline>(new GraphicsPipeline(context, m_resource.getType(), m_resource.getBuffer().handle, "read_ib_", *m_descriptorSetLayout)));
4573 	}
4574 
recordCommands(const VkCommandBuffer cmdBuffer)4575 	void recordCommands (const VkCommandBuffer cmdBuffer)
4576 	{
4577 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
4578 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
4579 
4580 		m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
4581 
4582 		// Insert a barrier so data written by the shader is available to the host
4583 		const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
4584 			m_pipelineStage,							// VkPipelineStageFlags2KHR			srcStageMask
4585 			VK_ACCESS_2_SHADER_WRITE_BIT_KHR,			// VkAccessFlags2KHR				srcAccessMask
4586 			VK_PIPELINE_STAGE_2_HOST_BIT_KHR,			// VkPipelineStageFlags2KHR			dstStageMask
4587 			VK_ACCESS_2_HOST_READ_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
4588 			**m_hostBuffer,								// VkBuffer							buffer
4589 			0u,											// VkDeviceSize						offset
4590 			m_hostBufferSizeBytes						// VkDeviceSize						size
4591 		);
4592 		VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
4593 		synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
4594 	}
4595 
getInSyncInfo(void) const4596 	SyncInfo getInSyncInfo (void) const
4597 	{
4598 		const SyncInfo syncInfo =
4599 		{
4600 			VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR,	// VkPipelineStageFlags		stageMask;
4601 			VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR,	// VkAccessFlags			accessMask;
4602 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			imageLayout;
4603 		};
4604 		return syncInfo;
4605 	}
4606 
getOutSyncInfo(void) const4607 	SyncInfo getOutSyncInfo (void) const
4608 	{
4609 		return emptySyncInfo;
4610 	}
4611 
getData(void) const4612 	Data getData (void) const
4613 	{
4614 		return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
4615 	}
4616 
setData(const Data &)4617 	void setData (const Data&)
4618 	{
4619 		DE_ASSERT(0);
4620 	}
4621 
4622 private:
4623 	OperationContext&			m_context;
4624 	Resource&					m_resource;
4625 	const VkShaderStageFlagBits	m_stage;
4626 	const VkPipelineStageFlags	m_pipelineStage;
4627 	const VkDeviceSize			m_hostBufferSizeBytes;
4628 	de::MovePtr<Buffer>			m_hostBuffer;
4629 	Move<VkDescriptorPool>		m_descriptorPool;
4630 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
4631 	Move<VkDescriptorSet>		m_descriptorSet;
4632 	de::MovePtr<Pipeline>		m_pipeline;
4633 };
4634 
4635 //! Prepare indirect buffer for a draw/dispatch call.
4636 class WriteImplementation : public Operation
4637 {
4638 public:
WriteImplementation(OperationContext & context,Resource & resource)4639 	WriteImplementation (OperationContext& context, Resource& resource)
4640 		: m_context			(context)
4641 		, m_resource		(resource)
4642 	{
4643 		switch (m_resource.getType())
4644 		{
4645 			case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
4646 			{
4647 				m_drawIndirect.vertexCount		= 6u;
4648 				m_drawIndirect.instanceCount	= 1u;
4649 				m_drawIndirect.firstVertex		= 0u;
4650 				m_drawIndirect.firstInstance	= 0u;
4651 
4652 				m_indirectData					= reinterpret_cast<deUint32*>(&m_drawIndirect);
4653 				m_expectedValue					= 6u;
4654 			}
4655 			break;
4656 
4657 			case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
4658 			{
4659 				m_drawIndexedIndirect.indexCount	= 6u;
4660 				m_drawIndexedIndirect.instanceCount	= 1u;
4661 				m_drawIndexedIndirect.firstIndex	= 0u;
4662 				m_drawIndexedIndirect.vertexOffset	= 0u;
4663 				m_drawIndexedIndirect.firstInstance	= 0u;
4664 
4665 				m_indirectData						= reinterpret_cast<deUint32*>(&m_drawIndexedIndirect);
4666 				m_expectedValue						= 6u;
4667 			}
4668 			break;
4669 
4670 			case RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH:
4671 			{
4672 				m_dispatchIndirect.x	= 7u;
4673 				m_dispatchIndirect.y	= 2u;
4674 				m_dispatchIndirect.z	= 1u;
4675 
4676 				m_indirectData			= reinterpret_cast<deUint32*>(&m_dispatchIndirect);
4677 				m_expectedValue			= 14u;
4678 			}
4679 			break;
4680 
4681 			default:
4682 				DE_ASSERT(0);
4683 				break;
4684 		}
4685 	}
4686 
recordCommands(const VkCommandBuffer cmdBuffer)4687 	void recordCommands (const VkCommandBuffer cmdBuffer)
4688 	{
4689 		const DeviceInterface&	vk	= m_context.getDeviceInterface();
4690 
4691 		vk.cmdUpdateBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, m_indirectData);
4692 	}
4693 
getInSyncInfo(void) const4694 	SyncInfo getInSyncInfo (void) const
4695 	{
4696 		return emptySyncInfo;
4697 	}
4698 
getOutSyncInfo(void) const4699 	SyncInfo getOutSyncInfo (void) const
4700 	{
4701 		const SyncInfo syncInfo =
4702 		{
4703 			VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,	// VkPipelineStageFlags		stageMask;
4704 			VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,		// VkAccessFlags			accessMask;
4705 			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			imageLayout;
4706 		};
4707 		return syncInfo;
4708 	}
4709 
getData(void) const4710 	Data getData (void) const
4711 	{
4712 		const Data data =
4713 		{
4714 			sizeof(deUint32),									// std::size_t		size;
4715 			reinterpret_cast<const deUint8*>(&m_expectedValue),	// const deUint8*	data;
4716 		};
4717 		return data;
4718 	}
4719 
setData(const Data &)4720 	void setData (const Data&)
4721 	{
4722 		DE_ASSERT(0);
4723 	}
4724 
4725 private:
4726 	OperationContext&				m_context;
4727 	Resource&						m_resource;
4728 	VkDrawIndirectCommand			m_drawIndirect;
4729 	VkDrawIndexedIndirectCommand	m_drawIndexedIndirect;
4730 	VkDispatchIndirectCommand		m_dispatchIndirect;
4731 	deUint32*						m_indirectData;
4732 	deUint32						m_expectedValue;	//! Side-effect value expected to be computed by a read (draw/dispatch) command.
4733 };
4734 
4735 class ReadSupport : public OperationSupport
4736 {
4737 public:
ReadSupport(const ResourceDescription & resourceDesc)4738 	ReadSupport (const ResourceDescription& resourceDesc)
4739 		: m_resourceDesc	(resourceDesc)
4740 	{
4741 		DE_ASSERT(isIndirectBuffer(m_resourceDesc.type));
4742 	}
4743 
initPrograms(SourceCollections & programCollection) const4744 	void initPrograms (SourceCollections& programCollection) const
4745 	{
4746 		std::ostringstream decl;
4747 		decl << "layout(set = 0, binding = 0, std140) coherent buffer Data {\n"
4748 			 << "    uint value;\n"
4749 			 << "} sb_out;\n";
4750 
4751 		std::ostringstream main;
4752 		main << "    atomicAdd(sb_out.value, 1u);\n";
4753 
4754 		// Vertex
4755 		{
4756 			std::ostringstream src;
4757 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4758 				<< "\n"
4759 				<< "layout(location = 0) in vec4 v_in_position;\n"
4760 				<< "\n"
4761 				<< "out " << s_perVertexBlock << ";\n"
4762 				<< "\n"
4763 				<< decl.str()
4764 				<< "\n"
4765 				<< "void main (void)\n"
4766 				<< "{\n"
4767 				<< "    gl_Position = v_in_position;\n"
4768 				<< main.str()
4769 				<< "}\n";
4770 
4771 			programCollection.glslSources.add("read_ib_vert") << glu::VertexSource(src.str());
4772 		}
4773 
4774 		// Fragment
4775 		{
4776 			std::ostringstream src;
4777 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4778 				<< "\n"
4779 				<< "layout(location = 0) out vec4 o_color;\n"
4780 				<< "\n"
4781 				<< "void main (void)\n"
4782 				<< "{\n"
4783 				<< "    o_color = vec4(1.0);\n"
4784 				<< "}\n";
4785 
4786 			programCollection.glslSources.add("read_ib_frag") << glu::FragmentSource(src.str());
4787 		}
4788 
4789 		// Compute
4790 		{
4791 			std::ostringstream src;
4792 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4793 				<< "\n"
4794 				<< "layout(local_size_x = 1) in;\n"
4795 				<< "\n"
4796 				<< decl.str()
4797 				<< "\n"
4798 				<< "void main (void)\n"
4799 				<< "{\n"
4800 				<< main.str()
4801 				<< "}\n";
4802 
4803 			programCollection.glslSources.add("read_ib_comp") << glu::ComputeSource(src.str());
4804 		}
4805 	}
4806 
getInResourceUsageFlags(void) const4807 	deUint32 getInResourceUsageFlags (void) const
4808 	{
4809 		return VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
4810 	}
4811 
getOutResourceUsageFlags(void) const4812 	deUint32 getOutResourceUsageFlags (void) const
4813 	{
4814 		return 0;
4815 	}
4816 
getQueueFlags(const OperationContext & context) const4817 	VkQueueFlags getQueueFlags (const OperationContext& context) const
4818 	{
4819 		DE_UNREF(context);
4820 		return (m_resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
4821 	}
4822 
build(OperationContext & context,Resource & resource) const4823 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4824 	{
4825 		return de::MovePtr<Operation>(new ReadImplementation(context, resource));
4826 	}
4827 
build(OperationContext &,Resource &,Resource &) const4828 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4829 	{
4830 		DE_ASSERT(0);
4831 		return de::MovePtr<Operation>();
4832 	}
4833 
4834 private:
4835 	const ResourceDescription	m_resourceDesc;
4836 };
4837 
4838 
4839 class WriteSupport : public OperationSupport
4840 {
4841 public:
WriteSupport(const ResourceDescription & resourceDesc)4842 	WriteSupport (const ResourceDescription& resourceDesc)
4843 	{
4844 		DE_ASSERT(isIndirectBuffer(resourceDesc.type));
4845 		DE_UNREF(resourceDesc);
4846 	}
4847 
getInResourceUsageFlags(void) const4848 	deUint32 getInResourceUsageFlags (void) const
4849 	{
4850 		return 0;
4851 	}
4852 
getOutResourceUsageFlags(void) const4853 	deUint32 getOutResourceUsageFlags (void) const
4854 	{
4855 		return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4856 	}
4857 
getQueueFlags(const OperationContext & context) const4858 	VkQueueFlags getQueueFlags (const OperationContext& context) const
4859 	{
4860 		DE_UNREF(context);
4861 		return VK_QUEUE_TRANSFER_BIT;
4862 	}
4863 
build(OperationContext & context,Resource & resource) const4864 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4865 	{
4866 		return de::MovePtr<Operation>(new WriteImplementation(context, resource));
4867 	}
4868 
build(OperationContext &,Resource &,Resource &) const4869 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4870 	{
4871 		DE_ASSERT(0);
4872 		return de::MovePtr<Operation>();
4873 	}
4874 };
4875 
4876 } // IndirectBuffer ns
4877 
4878 namespace VertexInput
4879 {
4880 
4881 enum DrawMode
4882 {
4883 	DRAW_MODE_VERTEX	= 0,
4884 	DRAW_MODE_INDEXED,
4885 };
4886 
4887 class Implementation : public Operation
4888 {
4889 public:
Implementation(OperationContext & context,Resource & resource,DrawMode drawMode)4890 	Implementation (OperationContext& context, Resource& resource, DrawMode drawMode)
4891 		: m_context		(context)
4892 		, m_resource	(resource)
4893 		, m_drawMode	(drawMode)
4894 	{
4895 		requireFeaturesForSSBOAccess (m_context, VK_SHADER_STAGE_VERTEX_BIT);
4896 
4897 		const DeviceInterface&		vk				= context.getDeviceInterface();
4898 		const VkDevice				device			= context.getDevice();
4899 		Allocator&					allocator		= context.getAllocator();
4900 		VkFormat					attributeFormat = VK_FORMAT_R32G32B32A32_UINT;
4901 		const VkDeviceSize			dataSizeBytes	= m_resource.getBuffer().size;
4902 
4903 		// allocate ssbo that will store data used for verification
4904 		{
4905 			m_outputBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
4906 				makeBufferCreateInfo(dataSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
4907 
4908 			const Allocation& alloc = m_outputBuffer->getAllocation();
4909 			deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(dataSizeBytes));
4910 			flushAlloc(vk, device, alloc);
4911 		}
4912 
4913 		// allocate buffer that will be used for vertex attributes when we use resource for indices
4914 		if (m_drawMode == DRAW_MODE_INDEXED)
4915 		{
4916 			attributeFormat = VK_FORMAT_R32_UINT;
4917 
4918 			m_inputBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
4919 				makeBufferCreateInfo(dataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
4920 
4921 			const Allocation& alloc = m_inputBuffer->getAllocation();
4922 			fillPattern(alloc.getHostPtr(), dataSizeBytes, true);
4923 			flushAlloc(vk, device, alloc);
4924 		}
4925 
4926 		m_descriptorSetLayout = DescriptorSetLayoutBuilder()
4927 			.addSingleBinding	(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
4928 			.build				(vk, device);
4929 
4930 		m_descriptorPool = DescriptorPoolBuilder()
4931 			.addType	(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4932 			.build		(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4933 
4934 		m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
4935 
4936 		const VkDescriptorBufferInfo outputBufferDescriptorInfo = makeDescriptorBufferInfo(m_outputBuffer->get(), 0ull, dataSizeBytes);
4937 		DescriptorSetUpdateBuilder()
4938 			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferDescriptorInfo)
4939 			.update		(vk, device);
4940 
4941 		// Color attachment
4942 		m_colorFormat						= VK_FORMAT_R8G8B8A8_UNORM;
4943 		m_colorImageSubresourceRange		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4944 		m_colorImageExtent					= makeExtent3D(16u, 16u, 1u);
4945 		m_colorAttachmentImage				= de::MovePtr<Image>(new Image(vk, device, allocator,
4946 			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4947 								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
4948 			MemoryRequirement::Any));
4949 
4950 		// Pipeline
4951 		m_colorAttachmentView	= makeImageView		(vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
4952 		m_renderPass			= makeRenderPass	(vk, device, m_colorFormat);
4953 		m_framebuffer			= makeFramebuffer	(vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height);
4954 		m_pipelineLayout		= makePipelineLayout(vk, device, *m_descriptorSetLayout);
4955 
4956 		m_pipeline = GraphicsPipelineBuilder()
4957 			.setPrimitiveTopology			(VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
4958 			.setRenderSize					(tcu::IVec2(static_cast<int>(m_colorImageExtent.width), static_cast<int>(m_colorImageExtent.height)))
4959 			.setVertexInputSingleAttribute	(attributeFormat, tcu::getPixelSize(mapVkFormat(attributeFormat)))
4960 			.setShader						(vk, device, VK_SHADER_STAGE_VERTEX_BIT,	context.getBinaryCollection().get("input_vert"), DE_NULL)
4961 			.setShader						(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,	context.getBinaryCollection().get("input_frag"), DE_NULL)
4962 			.build							(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData(), context.getResourceInterface());
4963 	}
4964 
recordCommands(const VkCommandBuffer cmdBuffer)4965 	void recordCommands (const VkCommandBuffer cmdBuffer)
4966 	{
4967 		const DeviceInterface&		vk						= m_context.getDeviceInterface();
4968 		const VkDeviceSize			dataSizeBytes			= m_resource.getBuffer().size;
4969 		SynchronizationWrapperPtr	synchronizationWrapper	= getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
4970 
4971 		// Change color attachment image layout
4972 		{
4973 			const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
4974 				VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,				// VkPipelineStageFlags2KHR			srcStageMask
4975 				(VkAccessFlags)0,										// VkAccessFlags2KHR				srcAccessMask
4976 				VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,	// VkPipelineStageFlags2KHR			dstStageMask
4977 				VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,				// VkAccessFlags2KHR				dstAccessMask
4978 				VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout					oldLayout
4979 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout					newLayout
4980 				**m_colorAttachmentImage,								// VkImage							image
4981 				m_colorImageSubresourceRange							// VkImageSubresourceRange			subresourceRange
4982 			);
4983 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
4984 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
4985 		}
4986 
4987 		{
4988 			const VkRect2D	renderArea	= makeRect2D(m_colorImageExtent);
4989 			const tcu::Vec4	clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
4990 
4991 			beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
4992 		}
4993 
4994 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4995 		vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
4996 
4997 		const VkDeviceSize vertexBufferOffset	= 0ull;
4998 		if (m_drawMode == DRAW_MODE_VERTEX)
4999 		{
5000 			const deUint32 count = static_cast<deUint32>(dataSizeBytes / sizeof(tcu::UVec4));
5001 			vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_resource.getBuffer().handle, &vertexBufferOffset);
5002 			vk.cmdDraw(cmdBuffer, count, 1u, 0u, 0u);
5003 		}
5004 		else // (m_drawMode == DRAW_MODE_INDEXED)
5005 		{
5006 			const deUint32 count = static_cast<deUint32>(dataSizeBytes / sizeof(deUint32));
5007 			vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &**m_inputBuffer, &vertexBufferOffset);
5008 			vk.cmdBindIndexBuffer(cmdBuffer, m_resource.getBuffer().handle, 0u, VK_INDEX_TYPE_UINT32);
5009 			vk.cmdDrawIndexed(cmdBuffer, count, 1, 0, 0, 0);
5010 		}
5011 
5012 		endRenderPass(vk, cmdBuffer);
5013 
5014 		// Insert a barrier so data written by the shader is available to the host
5015 		{
5016 			const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
5017 				VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR,		// VkPipelineStageFlags2KHR			srcStageMask
5018 				VK_ACCESS_2_SHADER_WRITE_BIT_KHR,				// VkAccessFlags2KHR				srcAccessMask
5019 				VK_PIPELINE_STAGE_2_HOST_BIT_KHR,				// VkPipelineStageFlags2KHR			dstStageMask
5020 				VK_ACCESS_2_HOST_READ_BIT_KHR,					// VkAccessFlags2KHR				dstAccessMask
5021 				**m_outputBuffer,								// VkBuffer							buffer
5022 				0u,												// VkDeviceSize						offset
5023 				m_resource.getBuffer().size						// VkDeviceSize						size
5024 			);
5025 			VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
5026 			synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
5027 		}
5028 	}
5029 
getInSyncInfo(void) const5030 	SyncInfo getInSyncInfo (void) const
5031 	{
5032 		const bool					usingIndexedDraw	= (m_drawMode == DRAW_MODE_INDEXED);
5033 		VkPipelineStageFlags2KHR	stageMask			= VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR;
5034 		VkAccessFlags2KHR			accessMask			= usingIndexedDraw ? VK_ACCESS_2_INDEX_READ_BIT_KHR
5035 																		   : VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR;
5036 
5037 		if (m_context.getSynchronizationType() == SynchronizationType::SYNCHRONIZATION2)
5038 		{
5039 			// test new stages added with VK_KHR_synchronization2 (no need to further duplicate those tests);
5040 			// with this operation we can test pre_rasterization, index_input and attribute_input flags;
5041 			// since this operation is executed for three buffers of different size we use diferent flags depending on the size
5042 			if (m_resource.getBuffer().size > MAX_UPDATE_BUFFER_SIZE)
5043 				stageMask = VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR;
5044 			else
5045 				stageMask = usingIndexedDraw ? VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR
5046 											 : VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR;
5047 		}
5048 
5049 		const SyncInfo syncInfo =
5050 		{
5051 			stageMask,									// VkPipelineStageFlags		stageMask;
5052 			accessMask,									// VkAccessFlags			accessMask;
5053 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			imageLayout;
5054 		};
5055 		return syncInfo;
5056 	}
5057 
getOutSyncInfo(void) const5058 	SyncInfo getOutSyncInfo (void) const
5059 	{
5060 		return emptySyncInfo;
5061 	}
5062 
getData(void) const5063 	Data getData (void) const
5064 	{
5065 		return getHostBufferData(m_context, *m_outputBuffer, m_resource.getBuffer().size);
5066 	}
5067 
setData(const Data & data)5068 	void setData (const Data& data)
5069 	{
5070 		setHostBufferData(m_context, *m_outputBuffer, data);
5071 	}
5072 
5073 private:
5074 	OperationContext&			m_context;
5075 	Resource&					m_resource;
5076 	DrawMode					m_drawMode;
5077 	de::MovePtr<Buffer>			m_inputBuffer;
5078 	de::MovePtr<Buffer>			m_outputBuffer;
5079 	Move<VkRenderPass>			m_renderPass;
5080 	Move<VkFramebuffer>			m_framebuffer;
5081 	Move<VkPipelineLayout>		m_pipelineLayout;
5082 	Move<VkPipeline>			m_pipeline;
5083 	VkFormat					m_colorFormat;
5084 	de::MovePtr<Image>			m_colorAttachmentImage;
5085 	Move<VkImageView>			m_colorAttachmentView;
5086 	VkExtent3D					m_colorImageExtent;
5087 	VkImageSubresourceRange		m_colorImageSubresourceRange;
5088 	Move<VkDescriptorPool>		m_descriptorPool;
5089 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
5090 	Move<VkDescriptorSet>		m_descriptorSet;
5091 };
5092 
5093 class Support : public OperationSupport
5094 {
5095 public:
Support(const ResourceDescription & resourceDesc,DrawMode drawMode)5096 	Support(const ResourceDescription& resourceDesc, DrawMode drawMode)
5097 		: m_resourceDesc	(resourceDesc)
5098 		, m_drawMode		(drawMode)
5099 	{
5100 		DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER || m_resourceDesc.type == RESOURCE_TYPE_INDEX_BUFFER);
5101 	}
5102 
initPrograms(SourceCollections & programCollection) const5103 	void initPrograms (SourceCollections& programCollection) const
5104 	{
5105 		// Vertex
5106 		{
5107 			std::ostringstream src;
5108 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n";
5109 			if (m_drawMode == DRAW_MODE_VERTEX)
5110 			{
5111 				src << "layout(location = 0) in uvec4 v_in_data;\n"
5112 					<< "layout(set = 0, binding = 0, std140) writeonly buffer Output {\n"
5113 					<< "    uvec4 data[" << m_resourceDesc.size.x() / sizeof(tcu::UVec4) << "];\n"
5114 					<< "} b_out;\n"
5115 					<< "\n"
5116 					<< "void main (void)\n"
5117 					<< "{\n"
5118 					<< "    b_out.data[gl_VertexIndex] = v_in_data;\n"
5119 					<< "    gl_PointSize = 1.0f;\n"
5120 					<< "}\n";
5121 			}
5122 			else // DRAW_MODE_INDEXED
5123 			{
5124 				src << "layout(location = 0) in uint v_in_data;\n"
5125 					<< "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
5126 					<< "    uint data[" << m_resourceDesc.size.x() / sizeof(deUint32) << "];\n"
5127 					<< "} b_out;\n"
5128 					<< "\n"
5129 					<< "void main (void)\n"
5130 					<< "{\n"
5131 					<< "    b_out.data[gl_VertexIndex] = v_in_data;\n"
5132 					<< "    gl_PointSize = 1.0f;\n"
5133 					<< "}\n";
5134 			}
5135 			programCollection.glslSources.add("input_vert") << glu::VertexSource(src.str());
5136 		}
5137 
5138 		// Fragment
5139 		{
5140 			std::ostringstream src;
5141 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
5142 				<< "\n"
5143 				<< "layout(location = 0) out vec4 o_color;\n"
5144 				<< "\n"
5145 				<< "void main (void)\n"
5146 				<< "{\n"
5147 				<< "    o_color = vec4(1.0);\n"
5148 				<< "}\n";
5149 			programCollection.glslSources.add("input_frag") << glu::FragmentSource(src.str());
5150 		}
5151 	}
5152 
getInResourceUsageFlags(void) const5153 	deUint32 getInResourceUsageFlags (void) const
5154 	{
5155 		return (m_drawMode == DRAW_MODE_VERTEX) ? VK_BUFFER_USAGE_VERTEX_BUFFER_BIT : VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
5156 	}
5157 
getOutResourceUsageFlags(void) const5158 	deUint32 getOutResourceUsageFlags (void) const
5159 	{
5160 		return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
5161 	}
5162 
getQueueFlags(const OperationContext &) const5163 	VkQueueFlags getQueueFlags (const OperationContext&) const
5164 	{
5165 		return VK_QUEUE_GRAPHICS_BIT;
5166 	}
5167 
build(OperationContext & context,Resource & resource) const5168 	de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
5169 	{
5170 		return de::MovePtr<Operation>(new Implementation(context, resource, m_drawMode));
5171 	}
5172 
build(OperationContext &,Resource &,Resource &) const5173 	de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
5174 	{
5175 		DE_ASSERT(0);
5176 		return de::MovePtr<Operation>();
5177 	}
5178 
5179 private:
5180 	const ResourceDescription	m_resourceDesc;
5181 	const DrawMode				m_drawMode;
5182 };
5183 
5184 } // VertexInput
5185 
5186 } // anonymous ns
5187 
OperationContext(Context & context,SynchronizationType syncType,PipelineCacheData & pipelineCacheData)5188 OperationContext::OperationContext (Context& context, SynchronizationType syncType, PipelineCacheData& pipelineCacheData)
5189 	: m_context				(context)
5190 	, m_syncType			(syncType)
5191 	, m_vki					(context.getInstanceInterface())
5192 	, m_vk					(context.getDeviceInterface())
5193 	, m_physicalDevice		(context.getPhysicalDevice())
5194 	, m_device				(context.getDevice())
5195 	, m_allocator			(context.getDefaultAllocator())
5196 	, m_progCollection		(context.getBinaryCollection())
5197 	, m_pipelineCacheData	(pipelineCacheData)
5198 {
5199 }
5200 
OperationContext(Context & context,SynchronizationType syncType,const DeviceInterface & vk,const VkDevice device,vk::Allocator & allocator,PipelineCacheData & pipelineCacheData)5201 OperationContext::OperationContext (Context&				context,
5202 									SynchronizationType		syncType,
5203 									const DeviceInterface&	vk,
5204 									const VkDevice			device,
5205 									vk::Allocator&			allocator,
5206 									PipelineCacheData&		pipelineCacheData)
5207 	: m_context				(context)
5208 	, m_syncType			(syncType)
5209 	, m_vki					(context.getInstanceInterface())
5210 	, m_vk					(vk)
5211 	, m_physicalDevice		(context.getPhysicalDevice())
5212 	, m_device				(device)
5213 	, m_allocator			(allocator)
5214 	, m_progCollection		(context.getBinaryCollection())
5215 	, m_pipelineCacheData	(pipelineCacheData)
5216 {
5217 }
5218 
OperationContext(Context & context,SynchronizationType syncType,const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::Allocator & allocator,vk::BinaryCollection & programCollection,PipelineCacheData & pipelineCacheData)5219 OperationContext::OperationContext (Context&						context,
5220 									SynchronizationType				syncType,
5221 									const vk::InstanceInterface&	vki,
5222 									const vk::DeviceInterface&		vkd,
5223 									vk::VkPhysicalDevice			physicalDevice,
5224 									vk::VkDevice					device,
5225 									vk::Allocator&					allocator,
5226 									vk::BinaryCollection&			programCollection,
5227 									PipelineCacheData&				pipelineCacheData)
5228 	: m_context				(context)
5229 	, m_syncType			(syncType)
5230 	, m_vki					(vki)
5231 	, m_vk					(vkd)
5232 	, m_physicalDevice		(physicalDevice)
5233 	, m_device				(device)
5234 	, m_allocator			(allocator)
5235 	, m_progCollection		(programCollection)
5236 	, m_pipelineCacheData	(pipelineCacheData)
5237 {
5238 }
5239 
Resource(OperationContext & context,const ResourceDescription & desc,const deUint32 usage,const vk::VkSharingMode sharingMode,const std::vector<deUint32> & queueFamilyIndex)5240 Resource::Resource (OperationContext& context, const ResourceDescription& desc, const deUint32 usage, const vk::VkSharingMode sharingMode, const std::vector<deUint32>& queueFamilyIndex)
5241 	: m_type	(desc.type)
5242 {
5243 	const DeviceInterface&		vk			= context.getDeviceInterface();
5244 	const InstanceInterface&	vki			= context.getInstanceInterface();
5245 	const VkDevice				device		= context.getDevice();
5246 	const VkPhysicalDevice		physDevice	= context.getPhysicalDevice();
5247 	Allocator&					allocator	= context.getAllocator();
5248 
5249 	if (m_type == RESOURCE_TYPE_BUFFER || m_type == RESOURCE_TYPE_INDEX_BUFFER || isIndirectBuffer(m_type))
5250 	{
5251 		m_bufferData = de::MovePtr<BufferResource>(new BufferResource(DE_NULL, 0u, static_cast<VkDeviceSize>(desc.size.x())));
5252 		VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_bufferData->size, usage);
5253 		bufferCreateInfo.sharingMode		= sharingMode;
5254 		if (queueFamilyIndex.size() > 0)
5255 		{
5256 			bufferCreateInfo.queueFamilyIndexCount	= static_cast<deUint32>(queueFamilyIndex.size());
5257 			bufferCreateInfo.pQueueFamilyIndices	= &queueFamilyIndex[0];
5258 		}
5259 		m_buffer				= de::MovePtr<Buffer>(new Buffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Any));
5260 		m_bufferData->handle	= **m_buffer;
5261 	}
5262 	else if (m_type == RESOURCE_TYPE_IMAGE)
5263 	{
5264 		m_imageData = de::MovePtr<ImageResource>(new ImageResource(
5265 			DE_NULL,
5266 			makeExtent3D(desc.size.x(), std::max(1, desc.size.y()), std::max(1, desc.size.z())),
5267 			desc.imageType,
5268 			desc.imageFormat,
5269 			makeImageSubresourceRange(desc.imageAspect, 0u, 1u, 0u, 1u),
5270 			makeImageSubresourceLayers(desc.imageAspect, 0u, 0u, 1u),
5271 			vk::VK_IMAGE_TILING_OPTIMAL
5272 		));
5273 		VkImageCreateInfo imageInfo		= makeImageCreateInfo(m_imageData->imageType, m_imageData->extent, m_imageData->format, usage, desc.imageSamples, m_imageData->tiling);
5274 		imageInfo.sharingMode			= sharingMode;
5275 		if (queueFamilyIndex.size() > 0)
5276 		{
5277 			imageInfo.queueFamilyIndexCount	= static_cast<deUint32>(queueFamilyIndex.size());
5278 			imageInfo.pQueueFamilyIndices	= &queueFamilyIndex[0];
5279 		}
5280 
5281 		VkImageFormatProperties	imageFormatProperties;
5282 		const VkResult formatResult		= vki.getPhysicalDeviceImageFormatProperties(physDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProperties);
5283 
5284 		if (formatResult != VK_SUCCESS)
5285 			TCU_THROW(NotSupportedError, "Image format is not supported");
5286 
5287 		if ((imageFormatProperties.sampleCounts & desc.imageSamples) != desc.imageSamples)
5288 			TCU_THROW(NotSupportedError, "Requested sample count is not supported");
5289 
5290 		m_image							= de::MovePtr<Image>(new Image(vk, device, allocator, imageInfo, MemoryRequirement::Any));
5291 		m_imageData->handle				= **m_image;
5292 	}
5293 	else
5294 		DE_ASSERT(0);
5295 }
5296 
Resource(ResourceType type,vk::Move<vk::VkBuffer> buffer,de::MovePtr<vk::Allocation> allocation,vk::VkDeviceSize offset,vk::VkDeviceSize size)5297 Resource::Resource (ResourceType				type,
5298 					vk::Move<vk::VkBuffer>		buffer,
5299 					de::MovePtr<vk::Allocation>	allocation,
5300 					vk::VkDeviceSize			offset,
5301 					vk::VkDeviceSize			size)
5302 	: m_type		(type)
5303 	, m_buffer		(new Buffer(buffer, allocation))
5304 	, m_bufferData	(de::MovePtr<BufferResource>(new BufferResource(m_buffer->get(), offset, size)))
5305 {
5306 	DE_ASSERT(type != RESOURCE_TYPE_IMAGE);
5307 }
5308 
Resource(vk::Move<vk::VkImage> image,de::MovePtr<vk::Allocation> allocation,const vk::VkExtent3D & extent,vk::VkImageType imageType,vk::VkFormat format,vk::VkImageSubresourceRange subresourceRange,vk::VkImageSubresourceLayers subresourceLayers,vk::VkImageTiling tiling)5309 Resource::Resource (vk::Move<vk::VkImage>			image,
5310 					de::MovePtr<vk::Allocation>		allocation,
5311 					const vk::VkExtent3D&			extent,
5312 					vk::VkImageType					imageType,
5313 					vk::VkFormat					format,
5314 					vk::VkImageSubresourceRange		subresourceRange,
5315 					vk::VkImageSubresourceLayers	subresourceLayers,
5316 					vk::VkImageTiling				tiling)
5317 	: m_type		(RESOURCE_TYPE_IMAGE)
5318 	, m_image		(new Image(image, allocation))
5319 	, m_imageData	(de::MovePtr<ImageResource>(new ImageResource(m_image->get(), extent, imageType, format, subresourceRange, subresourceLayers, tiling)))
5320 {
5321 }
5322 
getMemory(void) const5323 vk::VkDeviceMemory Resource::getMemory (void) const
5324 {
5325 	if (m_type == RESOURCE_TYPE_IMAGE)
5326 		return m_image->getAllocation().getMemory();
5327 	else
5328 		return m_buffer->getAllocation().getMemory();
5329 }
5330 
5331 //! \note This function exists for performance reasons. We're creating a lot of tests and checking requirements here
5332 //!       before creating an OperationSupport object is faster.
isResourceSupported(const OperationName opName,const ResourceDescription & resourceDesc)5333 bool isResourceSupported (const OperationName opName, const ResourceDescription& resourceDesc)
5334 {
5335 	switch (opName)
5336 	{
5337 		case OPERATION_NAME_WRITE_FILL_BUFFER:
5338 		case OPERATION_NAME_WRITE_COPY_BUFFER:
5339 		case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:
5340 		case OPERATION_NAME_WRITE_SSBO_VERTEX:
5341 		case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL:
5342 		case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION:
5343 		case OPERATION_NAME_WRITE_SSBO_GEOMETRY:
5344 		case OPERATION_NAME_WRITE_SSBO_FRAGMENT:
5345 		case OPERATION_NAME_WRITE_SSBO_COMPUTE:
5346 		case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT:
5347 		case OPERATION_NAME_READ_COPY_BUFFER:
5348 		case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:
5349 		case OPERATION_NAME_READ_SSBO_VERTEX:
5350 		case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL:
5351 		case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION:
5352 		case OPERATION_NAME_READ_SSBO_GEOMETRY:
5353 		case OPERATION_NAME_READ_SSBO_FRAGMENT:
5354 		case OPERATION_NAME_READ_SSBO_COMPUTE:
5355 		case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT:
5356 		case OPERATION_NAME_READ_VERTEX_INPUT:
5357 			return resourceDesc.type == RESOURCE_TYPE_BUFFER;
5358 
5359 		case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:
5360 		case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:
5361 			return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DRAW;
5362 
5363 		case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:
5364 		case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:
5365 			return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED;
5366 
5367 		case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:
5368 		case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:
5369 			return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH;
5370 
5371 		case OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER:
5372 		case OPERATION_NAME_READ_INDEX_INPUT:
5373 			return resourceDesc.type == RESOURCE_TYPE_INDEX_BUFFER;
5374 
5375 		case OPERATION_NAME_WRITE_UPDATE_BUFFER:
5376 			return resourceDesc.type == RESOURCE_TYPE_BUFFER && resourceDesc.size.x() <= MAX_UPDATE_BUFFER_SIZE;
5377 
5378 		case OPERATION_NAME_WRITE_COPY_IMAGE:
5379 		case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:
5380 		case OPERATION_NAME_READ_COPY_IMAGE:
5381 		case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:
5382 			return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5383 
5384 		case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:
5385 			return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageType != VK_IMAGE_TYPE_3D
5386 				&& resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5387 
5388 		case OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE:
5389 		case OPERATION_NAME_READ_RESOLVE_IMAGE:
5390 			return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5391 				&& resourceDesc.imageSamples != VK_SAMPLE_COUNT_1_BIT;
5392 
5393 		case OPERATION_NAME_WRITE_BLIT_IMAGE:
5394 		case OPERATION_NAME_READ_BLIT_IMAGE:
5395 		case OPERATION_NAME_WRITE_IMAGE_VERTEX:
5396 		case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:
5397 		case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:
5398 		case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:
5399 		case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:
5400 		case OPERATION_NAME_WRITE_IMAGE_COMPUTE:
5401 		case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT:
5402 		case OPERATION_NAME_READ_IMAGE_VERTEX:
5403 		case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:
5404 		case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:
5405 		case OPERATION_NAME_READ_IMAGE_GEOMETRY:
5406 		case OPERATION_NAME_READ_IMAGE_FRAGMENT:
5407 		case OPERATION_NAME_READ_IMAGE_COMPUTE:
5408 		case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT:
5409 			return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5410 				&& resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5411 
5412 		case OPERATION_NAME_READ_UBO_VERTEX:
5413 		case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL:
5414 		case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION:
5415 		case OPERATION_NAME_READ_UBO_GEOMETRY:
5416 		case OPERATION_NAME_READ_UBO_FRAGMENT:
5417 		case OPERATION_NAME_READ_UBO_COMPUTE:
5418 		case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT:
5419 			return resourceDesc.type == RESOURCE_TYPE_BUFFER && resourceDesc.size.x() <= MAX_UBO_RANGE;
5420 
5421 		case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:
5422 			return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5423 				&& resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5424 
5425 		case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:
5426 			return resourceDesc.type == RESOURCE_TYPE_IMAGE && (resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
5427 				&& resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5428 
5429 		case OPERATION_NAME_WRITE_DRAW:
5430 		case OPERATION_NAME_WRITE_DRAW_INDEXED:
5431 		case OPERATION_NAME_WRITE_DRAW_INDIRECT:
5432 		case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:
5433 			return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageType == VK_IMAGE_TYPE_2D
5434 				&& (resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0
5435 				&& resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5436 
5437 		case OPERATION_NAME_COPY_BUFFER:
5438 		case OPERATION_NAME_COPY_SSBO_VERTEX:
5439 		case OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL:
5440 		case OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION:
5441 		case OPERATION_NAME_COPY_SSBO_GEOMETRY:
5442 		case OPERATION_NAME_COPY_SSBO_FRAGMENT:
5443 		case OPERATION_NAME_COPY_SSBO_COMPUTE:
5444 		case OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT:
5445 			return resourceDesc.type == RESOURCE_TYPE_BUFFER;
5446 
5447 		case OPERATION_NAME_COPY_IMAGE:
5448 		case OPERATION_NAME_BLIT_IMAGE:
5449 		case OPERATION_NAME_COPY_IMAGE_VERTEX:
5450 		case OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL:
5451 		case OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION:
5452 		case OPERATION_NAME_COPY_IMAGE_GEOMETRY:
5453 		case OPERATION_NAME_COPY_IMAGE_FRAGMENT:
5454 		case OPERATION_NAME_COPY_IMAGE_COMPUTE:
5455 		case OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT:
5456 			return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5457 				&& resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5458 
5459 		default:
5460 			DE_ASSERT(0);
5461 			return false;
5462 	}
5463 }
5464 
getOperationName(const OperationName opName)5465 std::string getOperationName (const OperationName opName)
5466 {
5467 	switch (opName)
5468 	{
5469 		case OPERATION_NAME_WRITE_FILL_BUFFER:						return "write_fill_buffer";
5470 		case OPERATION_NAME_WRITE_UPDATE_BUFFER:					return "write_update_buffer";
5471 		case OPERATION_NAME_WRITE_COPY_BUFFER:						return "write_copy_buffer";
5472 		case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:				return "write_copy_buffer_to_image";
5473 		case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:				return "write_copy_image_to_buffer";
5474 		case OPERATION_NAME_WRITE_COPY_IMAGE:						return "write_copy_image";
5475 		case OPERATION_NAME_WRITE_BLIT_IMAGE:						return "write_blit_image";
5476 		case OPERATION_NAME_WRITE_SSBO_VERTEX:						return "write_ssbo_vertex";
5477 		case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL:		return "write_ssbo_tess_control";
5478 		case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION:		return "write_ssbo_tess_eval";
5479 		case OPERATION_NAME_WRITE_SSBO_GEOMETRY:					return "write_ssbo_geometry";
5480 		case OPERATION_NAME_WRITE_SSBO_FRAGMENT:					return "write_ssbo_fragment";
5481 		case OPERATION_NAME_WRITE_SSBO_COMPUTE:						return "write_ssbo_compute";
5482 		case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT:			return "write_ssbo_compute_indirect";
5483 		case OPERATION_NAME_WRITE_IMAGE_VERTEX:						return "write_image_vertex";
5484 		case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:		return "write_image_tess_control";
5485 		case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:	return "write_image_tess_eval";
5486 		case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:					return "write_image_geometry";
5487 		case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:					return "write_image_fragment";
5488 		case OPERATION_NAME_WRITE_IMAGE_COMPUTE:					return "write_image_compute";
5489 		case OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE:		return "write_image_compute_multisample";
5490 		case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT:			return "write_image_compute_indirect";
5491 		case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:				return "write_clear_color_image";
5492 		case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:		return "write_clear_depth_stencil_image";
5493 		case OPERATION_NAME_WRITE_DRAW:								return "write_draw";
5494 		case OPERATION_NAME_WRITE_DRAW_INDEXED:						return "write_draw_indexed";
5495 		case OPERATION_NAME_WRITE_DRAW_INDIRECT:					return "write_draw_indirect";
5496 		case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:			return "write_draw_indexed_indirect";
5497 		case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:				return "write_clear_attachments";
5498 		case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:				return "write_indirect_buffer_draw";
5499 		case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:		return "write_indirect_buffer_draw_indexed";
5500 		case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:			return "write_indirect_buffer_dispatch";
5501 		case OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER:				return "write_update_index_buffer";
5502 
5503 		case OPERATION_NAME_READ_COPY_BUFFER:						return "read_copy_buffer";
5504 		case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:				return "read_copy_buffer_to_image";
5505 		case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:				return "read_copy_image_to_buffer";
5506 		case OPERATION_NAME_READ_COPY_IMAGE:						return "read_copy_image";
5507 		case OPERATION_NAME_READ_BLIT_IMAGE:						return "read_blit_image";
5508 		case OPERATION_NAME_READ_RESOLVE_IMAGE:						return "read_resolve_image";
5509 		case OPERATION_NAME_READ_UBO_VERTEX:						return "read_ubo_vertex";
5510 		case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL:			return "read_ubo_tess_control";
5511 		case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION:		return "read_ubo_tess_eval";
5512 		case OPERATION_NAME_READ_UBO_GEOMETRY:						return "read_ubo_geometry";
5513 		case OPERATION_NAME_READ_UBO_FRAGMENT:						return "read_ubo_fragment";
5514 		case OPERATION_NAME_READ_UBO_COMPUTE:						return "read_ubo_compute";
5515 		case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT:				return "read_ubo_compute_indirect";
5516 		case OPERATION_NAME_READ_SSBO_VERTEX:						return "read_ssbo_vertex";
5517 		case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL:			return "read_ssbo_tess_control";
5518 		case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION:		return "read_ssbo_tess_eval";
5519 		case OPERATION_NAME_READ_SSBO_GEOMETRY:						return "read_ssbo_geometry";
5520 		case OPERATION_NAME_READ_SSBO_FRAGMENT:						return "read_ssbo_fragment";
5521 		case OPERATION_NAME_READ_SSBO_COMPUTE:						return "read_ssbo_compute";
5522 		case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT:				return "read_ssbo_compute_indirect";
5523 		case OPERATION_NAME_READ_IMAGE_VERTEX:						return "read_image_vertex";
5524 		case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:		return "read_image_tess_control";
5525 		case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:		return "read_image_tess_eval";
5526 		case OPERATION_NAME_READ_IMAGE_GEOMETRY:					return "read_image_geometry";
5527 		case OPERATION_NAME_READ_IMAGE_FRAGMENT:					return "read_image_fragment";
5528 		case OPERATION_NAME_READ_IMAGE_COMPUTE:						return "read_image_compute";
5529 		case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT:			return "read_image_compute_indirect";
5530 		case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:				return "read_indirect_buffer_draw";
5531 		case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:		return "read_indirect_buffer_draw_indexed";
5532 		case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:			return "read_indirect_buffer_dispatch";
5533 		case OPERATION_NAME_READ_VERTEX_INPUT:						return "read_vertex_input";
5534 		case OPERATION_NAME_READ_INDEX_INPUT:						return "read_index_input";
5535 
5536 		case OPERATION_NAME_COPY_BUFFER:							return "copy_buffer";
5537 		case OPERATION_NAME_COPY_IMAGE:								return "copy_image";
5538 		case OPERATION_NAME_BLIT_IMAGE:								return "blit_image";
5539 		case OPERATION_NAME_COPY_SSBO_VERTEX:						return "copy_buffer_vertex";
5540 		case OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL:			return "copy_ssbo_tess_control";
5541 		case OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION:		return "copy_ssbo_tess_eval";
5542 		case OPERATION_NAME_COPY_SSBO_GEOMETRY:						return "copy_ssbo_geometry";
5543 		case OPERATION_NAME_COPY_SSBO_FRAGMENT:						return "copy_ssbo_fragment";
5544 		case OPERATION_NAME_COPY_SSBO_COMPUTE:						return "copy_ssbo_compute";
5545 		case OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT:				return "copy_ssbo_compute_indirect";
5546 		case OPERATION_NAME_COPY_IMAGE_VERTEX:						return "copy_image_vertex";
5547 		case OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL:		return "copy_image_tess_control";
5548 		case OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION:		return "copy_image_tess_eval";
5549 		case OPERATION_NAME_COPY_IMAGE_GEOMETRY:					return "copy_image_geometry";
5550 		case OPERATION_NAME_COPY_IMAGE_FRAGMENT:					return "copy_image_fragment";
5551 		case OPERATION_NAME_COPY_IMAGE_COMPUTE:						return "copy_image_compute";
5552 		case OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT:			return "copy_image_compute_indirect";
5553 		default:
5554 			DE_ASSERT(0);
5555 			return "";
5556 	}
5557 }
5558 
makeOperationSupport(const OperationName opName,const ResourceDescription & resourceDesc)5559 de::MovePtr<OperationSupport> makeOperationSupport (const OperationName opName, const ResourceDescription& resourceDesc)
5560 {
5561 	switch (opName)
5562 	{
5563 		case OPERATION_NAME_WRITE_FILL_BUFFER:						return de::MovePtr<OperationSupport>(new FillUpdateBuffer	::Support		(resourceDesc, FillUpdateBuffer::BUFFER_OP_FILL));
5564 		case OPERATION_NAME_WRITE_UPDATE_BUFFER:					return de::MovePtr<OperationSupport>(new FillUpdateBuffer	::Support		(resourceDesc, FillUpdateBuffer::BUFFER_OP_UPDATE));
5565 		case OPERATION_NAME_WRITE_COPY_BUFFER:						return de::MovePtr<OperationSupport>(new CopyBuffer			::Support		(resourceDesc, ACCESS_MODE_WRITE));
5566 		case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:				return de::MovePtr<OperationSupport>(new CopyBufferToImage	::Support		(resourceDesc, ACCESS_MODE_WRITE));
5567 		case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:				return de::MovePtr<OperationSupport>(new CopyImageToBuffer	::Support		(resourceDesc, ACCESS_MODE_WRITE));
5568 		case OPERATION_NAME_WRITE_COPY_IMAGE:						return de::MovePtr<OperationSupport>(new CopyBlitResolveImage	::Support	(resourceDesc, CopyBlitResolveImage::TYPE_COPY, ACCESS_MODE_WRITE));
5569 		case OPERATION_NAME_WRITE_BLIT_IMAGE:						return de::MovePtr<OperationSupport>(new CopyBlitResolveImage	::Support	(resourceDesc, CopyBlitResolveImage::TYPE_BLIT, ACCESS_MODE_WRITE));
5570 		case OPERATION_NAME_WRITE_SSBO_VERTEX:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_VERTEX_BIT));
5571 		case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL:		return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5572 		case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION:		return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5573 		case OPERATION_NAME_WRITE_SSBO_GEOMETRY:					return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_GEOMETRY_BIT));
5574 		case OPERATION_NAME_WRITE_SSBO_FRAGMENT:					return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_FRAGMENT_BIT));
5575 		case OPERATION_NAME_WRITE_SSBO_COMPUTE:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT));
5576 		case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT:			return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5577 		case OPERATION_NAME_WRITE_IMAGE_VERTEX:						return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_VERTEX_BIT));
5578 		case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:		return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5579 		case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:	return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5580 		case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:					return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_GEOMETRY_BIT));
5581 		case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:					return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_FRAGMENT_BIT));
5582 		case OPERATION_NAME_WRITE_IMAGE_COMPUTE:					return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT));
5583 		case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT:			return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5584 		case OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE:		return de::MovePtr<OperationSupport>(new ShaderAccess		::MSImageSupport(resourceDesc));
5585 		case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:				return de::MovePtr<OperationSupport>(new ClearImage			::Support		(resourceDesc, ClearImage::CLEAR_MODE_COLOR));
5586 		case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:		return de::MovePtr<OperationSupport>(new ClearImage			::Support		(resourceDesc, ClearImage::CLEAR_MODE_DEPTH_STENCIL));
5587 		case OPERATION_NAME_WRITE_DRAW:								return de::MovePtr<OperationSupport>(new Draw				::Support		(resourceDesc, Draw::DRAW_CALL_DRAW));
5588 		case OPERATION_NAME_WRITE_DRAW_INDEXED:						return de::MovePtr<OperationSupport>(new Draw				::Support		(resourceDesc, Draw::DRAW_CALL_DRAW_INDEXED));
5589 		case OPERATION_NAME_WRITE_DRAW_INDIRECT:					return de::MovePtr<OperationSupport>(new Draw				::Support		(resourceDesc, Draw::DRAW_CALL_DRAW_INDIRECT));
5590 		case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:			return de::MovePtr<OperationSupport>(new Draw				::Support		(resourceDesc, Draw::DRAW_CALL_DRAW_INDEXED_INDIRECT));
5591 		case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:				return de::MovePtr<OperationSupport>(new ClearAttachments	::Support		(resourceDesc));
5592 		case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:				return de::MovePtr<OperationSupport>(new IndirectBuffer		::WriteSupport	(resourceDesc));
5593 		case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:		return de::MovePtr<OperationSupport>(new IndirectBuffer		::WriteSupport	(resourceDesc));
5594 		case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:			return de::MovePtr<OperationSupport>(new IndirectBuffer		::WriteSupport	(resourceDesc));
5595 		case OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER:				return de::MovePtr<OperationSupport>(new FillUpdateBuffer	::Support		(resourceDesc, FillUpdateBuffer::BUFFER_OP_UPDATE_WITH_INDEX_PATTERN));
5596 
5597 		case OPERATION_NAME_READ_COPY_BUFFER:						return de::MovePtr<OperationSupport>(new CopyBuffer			::Support		(resourceDesc, ACCESS_MODE_READ));
5598 		case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:				return de::MovePtr<OperationSupport>(new CopyBufferToImage	::Support		(resourceDesc, ACCESS_MODE_READ));
5599 		case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:				return de::MovePtr<OperationSupport>(new CopyImageToBuffer	::Support		(resourceDesc, ACCESS_MODE_READ));
5600 		case OPERATION_NAME_READ_COPY_IMAGE:						return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::Support		(resourceDesc, CopyBlitResolveImage::TYPE_COPY,		ACCESS_MODE_READ));
5601 		case OPERATION_NAME_READ_BLIT_IMAGE:						return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::Support		(resourceDesc, CopyBlitResolveImage::TYPE_BLIT,		ACCESS_MODE_READ));
5602 		case OPERATION_NAME_READ_RESOLVE_IMAGE:						return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::Support		(resourceDesc, CopyBlitResolveImage::TYPE_RESOLVE,	ACCESS_MODE_READ));
5603 		case OPERATION_NAME_READ_UBO_VERTEX:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
5604 		case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL:			return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5605 		case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION:		return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5606 		case OPERATION_NAME_READ_UBO_GEOMETRY:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
5607 		case OPERATION_NAME_READ_UBO_FRAGMENT:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
5608 		case OPERATION_NAME_READ_UBO_COMPUTE:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
5609 		case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT:				return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5610 		case OPERATION_NAME_READ_SSBO_VERTEX:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
5611 		case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL:			return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5612 		case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION:		return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5613 		case OPERATION_NAME_READ_SSBO_GEOMETRY:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
5614 		case OPERATION_NAME_READ_SSBO_FRAGMENT:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
5615 		case OPERATION_NAME_READ_SSBO_COMPUTE:						return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
5616 		case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT:				return de::MovePtr<OperationSupport>(new ShaderAccess		::BufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5617 		case OPERATION_NAME_READ_IMAGE_VERTEX:						return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
5618 		case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:		return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5619 		case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:		return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5620 		case OPERATION_NAME_READ_IMAGE_GEOMETRY:					return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
5621 		case OPERATION_NAME_READ_IMAGE_FRAGMENT:					return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
5622 		case OPERATION_NAME_READ_IMAGE_COMPUTE:						return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
5623 		case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT:			return de::MovePtr<OperationSupport>(new ShaderAccess		::ImageSupport	(resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5624 		case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:				return de::MovePtr<OperationSupport>(new IndirectBuffer		::ReadSupport	(resourceDesc));
5625 		case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:		return de::MovePtr<OperationSupport>(new IndirectBuffer		::ReadSupport	(resourceDesc));
5626 		case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:			return de::MovePtr<OperationSupport>(new IndirectBuffer		::ReadSupport	(resourceDesc));
5627 		case OPERATION_NAME_READ_VERTEX_INPUT:						return de::MovePtr<OperationSupport>(new VertexInput		::Support		(resourceDesc, VertexInput::DRAW_MODE_VERTEX));
5628 		case OPERATION_NAME_READ_INDEX_INPUT:						return de::MovePtr<OperationSupport>(new VertexInput		::Support		(resourceDesc, VertexInput::DRAW_MODE_INDEXED));
5629 
5630 		case OPERATION_NAME_COPY_BUFFER:							return de::MovePtr<OperationSupport>(new CopyBuffer			::CopySupport		(resourceDesc));
5631 		case OPERATION_NAME_COPY_IMAGE:								return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::CopySupport		(resourceDesc, CopyBlitResolveImage::TYPE_COPY));
5632 		case OPERATION_NAME_BLIT_IMAGE:								return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::CopySupport		(resourceDesc, CopyBlitResolveImage::TYPE_BLIT));
5633 		case OPERATION_NAME_COPY_SSBO_VERTEX:						return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyBufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_VERTEX_BIT));
5634 		case OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL:			return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyBufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5635 		case OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION:		return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyBufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5636 		case OPERATION_NAME_COPY_SSBO_GEOMETRY:						return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyBufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_GEOMETRY_BIT));
5637 		case OPERATION_NAME_COPY_SSBO_FRAGMENT:						return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyBufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_FRAGMENT_BIT));
5638 		case OPERATION_NAME_COPY_SSBO_COMPUTE:						return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyBufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_COMPUTE_BIT));
5639 		case OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT:				return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyBufferSupport	(resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5640 		case OPERATION_NAME_COPY_IMAGE_VERTEX:						return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyImageSupport	(resourceDesc, VK_SHADER_STAGE_VERTEX_BIT));
5641 		case OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL:		return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyImageSupport	(resourceDesc, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5642 		case OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION:		return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyImageSupport	(resourceDesc, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5643 		case OPERATION_NAME_COPY_IMAGE_GEOMETRY:					return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyImageSupport	(resourceDesc, VK_SHADER_STAGE_GEOMETRY_BIT));
5644 		case OPERATION_NAME_COPY_IMAGE_FRAGMENT:					return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyImageSupport	(resourceDesc, VK_SHADER_STAGE_FRAGMENT_BIT));
5645 		case OPERATION_NAME_COPY_IMAGE_COMPUTE:						return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyImageSupport	(resourceDesc, VK_SHADER_STAGE_COMPUTE_BIT));
5646 		case OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT:			return de::MovePtr<OperationSupport>(new ShaderAccess		::CopyImageSupport	(resourceDesc, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5647 
5648 		default:
5649 			DE_ASSERT(0);
5650 			return de::MovePtr<OperationSupport>();
5651 	}
5652 }
5653 
5654 } // synchronization
5655 } // vkt
5656