• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2021 Google Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Transient attachment tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktFragmentOperationsTransientAttachmentTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 
29 #include "vkDefs.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38 
39 #include "tcuImageCompare.hpp"
40 #include "tcuTestLog.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "tcuVector.hpp"
43 
44 #include "deUniquePtr.hpp"
45 
46 namespace vkt
47 {
48 namespace FragmentOperations
49 {
50 using namespace vk;
51 using de::UniquePtr;
52 
53 namespace
54 {
55 
56 enum class TestMode
57 {
58 	MODE_INVALID	= 1u << 0,
59 	MODE_COLOR		= 1u << 1,
60 	MODE_DEPTH		= 1u << 2,
61 	MODE_STENCIL	= 1u << 3
62 };
63 
memoryPropertyFlagBitToString(VkMemoryPropertyFlags flagBit)64 const char* memoryPropertyFlagBitToString(VkMemoryPropertyFlags flagBit)
65 {
66 	switch (flagBit)
67 	{
68 	case VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT:
69 		return "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT";
70 
71 	case VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT:
72 		return "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT";
73 
74 	case VK_MEMORY_PROPERTY_HOST_COHERENT_BIT:
75 		return "VK_MEMORY_PROPERTY_HOST_COHERENT_BIT";
76 
77 	case VK_MEMORY_PROPERTY_HOST_CACHED_BIT:
78 		return "VK_MEMORY_PROPERTY_HOST_CACHED_BIT";
79 
80 	case VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT:
81 		return "VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT";
82 
83 	case VK_MEMORY_PROPERTY_PROTECTED_BIT:
84 		return "VK_MEMORY_PROPERTY_PROTECTED_BIT";
85 
86 #ifndef CTS_USES_VULKANSC
87 	case VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD:
88 		return "VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD";
89 
90 	case VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD:
91 		return "VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD";
92 
93 	case VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV:
94 		return "VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV";
95 #endif // CTS_USES_VULKANSC
96 
97 	default:
98 		TCU_THROW(InternalError, "Unknown memory property flag bit");
99 	}
100 };
101 
getSupportedStencilFormat(const VkPhysicalDevice physDevice,const InstanceInterface & instanceInterface)102 VkFormat getSupportedStencilFormat(const VkPhysicalDevice physDevice, const InstanceInterface& instanceInterface)
103 {
104 	static const VkFormat stencilFormats[] =
105 	{
106 		VK_FORMAT_D16_UNORM_S8_UINT,
107 		VK_FORMAT_D24_UNORM_S8_UINT,
108 		VK_FORMAT_D32_SFLOAT_S8_UINT,
109 	};
110 
111 	for (const auto& sFormat : stencilFormats)
112 	{
113 		VkFormatProperties formatProps;
114 		instanceInterface.getPhysicalDeviceFormatProperties(physDevice, sFormat, &formatProps);
115 
116 		if ((formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
117 		{
118 			return sFormat;
119 		};
120 	}
121 
122 	return VK_FORMAT_UNDEFINED;
123 }
124 
getMemoryTypeIndices(VkMemoryPropertyFlags propertyFlag,const VkPhysicalDeviceMemoryProperties & pMemoryProperties)125 std::vector<deUint32> getMemoryTypeIndices(VkMemoryPropertyFlags propertyFlag, const VkPhysicalDeviceMemoryProperties& pMemoryProperties)
126 {
127 	std::vector<deUint32> indices;
128 	for (deUint32 typeIndex = 0u; typeIndex < pMemoryProperties.memoryTypeCount; ++typeIndex)
129 	{
130 		if ((pMemoryProperties.memoryTypes[typeIndex].propertyFlags & propertyFlag) == propertyFlag)
131 			indices.push_back(typeIndex);
132 	}
133 	return indices;
134 }
135 
makeImageCreateInfo(const VkFormat format,const tcu::IVec2 & size,VkImageUsageFlags usage)136 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const tcu::IVec2& size, VkImageUsageFlags usage)
137 {
138 	const VkImageCreateInfo imageParams =
139 	{
140 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
141 		DE_NULL,								// const void*				pNext;
142 		(VkImageCreateFlags)0,					// VkImageCreateFlags		flags;
143 		VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
144 		format,									// VkFormat					format;
145 		makeExtent3D(size.x(), size.y(), 1),	// VkExtent3D				extent;
146 		1u,										// deUint32					mipLevels;
147 		1u,										// deUint32					arrayLayers;
148 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
149 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
150 		usage,									// VkImageUsageFlags		usage;
151 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
152 		0u,										// deUint32					queueFamilyIndexCount;
153 		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
154 		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
155 	};
156 	return imageParams;
157 }
158 
makeAttachment(const VkFormat format,const VkAttachmentLoadOp loadOp,const VkAttachmentStoreOp storeOp,const VkImageLayout initialLayout,const VkImageLayout finalLayout)159 VkAttachmentDescription makeAttachment (
160 	 const VkFormat				format,
161 	 const VkAttachmentLoadOp	loadOp,
162 	 const VkAttachmentStoreOp	storeOp,
163 	 const VkImageLayout		initialLayout,
164 	 const VkImageLayout		finalLayout)
165 {
166 	const tcu::TextureFormat		tcuFormat		= mapVkFormat(format);
167 	const bool						hasStencil		= (tcuFormat.order == tcu::TextureFormat::DS
168 													|| tcuFormat.order == tcu::TextureFormat::S);
169 
170 	const VkAttachmentDescription	attachmentDesc	=
171 	{
172 		VkAttachmentDescriptionFlags(0),							// VkAttachmentDescriptionFlags	flags;
173 		format,														// VkFormat						format;
174 		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits		samples;
175 		loadOp,														// VkAttachmentLoadOp			loadOp;
176 		storeOp,													// VkAttachmentStoreOp			storeOp;
177 		hasStencil ? loadOp		: VK_ATTACHMENT_LOAD_OP_DONT_CARE,	// VkAttachmentLoadOp			stencilLoadOp;
178 		hasStencil ? storeOp	: VK_ATTACHMENT_STORE_OP_DONT_CARE,	// VkAttachmentStoreOp			stencilStoreOp;
179 		initialLayout,												// VkImageLayout				initialLayout;
180 		finalLayout													// VkImageLayout				finalLayout;
181 	};
182 
183 	return attachmentDesc;
184 }
185 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const std::vector<VkAttachmentDescription> attachmentDescriptions,const bool hasInputAttachment)186 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, const VkDevice device, const std::vector<VkAttachmentDescription> attachmentDescriptions, const bool hasInputAttachment)
187 {
188 	const tcu::TextureFormat					tcuFormat				= mapVkFormat(attachmentDescriptions[0].format);
189 	const bool									hasDepthStencil			= (tcuFormat.order == tcu::TextureFormat::DS
190 																		|| tcuFormat.order == tcu::TextureFormat::S
191 																		|| tcuFormat.order == tcu::TextureFormat::D);
192 
193 	std::vector< VkAttachmentReference>			testReferences;
194 	const deUint32								maxAttachmentIndex		= deUint32(attachmentDescriptions.size()) - 1u;
195 
196 	for (deUint32 ref = 0; ref < attachmentDescriptions.size(); ref++)
197 	{
198 		testReferences.push_back({ ref, attachmentDescriptions[ref].finalLayout });
199 	}
200 
201 	const VkSubpassDescription					subpassDescription		=
202 	{
203 		(VkSubpassDescriptionFlags)0,															// VkSubpassDescriptionFlags		flags
204 		VK_PIPELINE_BIND_POINT_GRAPHICS,														// VkPipelineBindPoint				pipelineBindPoint
205 		hasInputAttachment ? 1u :0u,															// deUint32							inputAttachmentCount
206 		hasInputAttachment ? &testReferences[0] : DE_NULL,										// const VkAttachmentReference*		pInputAttachments
207 		!hasDepthStencil || hasInputAttachment ? 1u : 0u,										// deUint32							colorAttachmentCount
208 		!hasDepthStencil || hasInputAttachment ? &testReferences[maxAttachmentIndex] : DE_NULL,	// const VkAttachmentReference*		pColorAttachments
209 		DE_NULL,																				// const VkAttachmentReference*		pResolveAttachments
210 		hasDepthStencil && !hasInputAttachment ? &testReferences[0] : DE_NULL,					// const VkAttachmentReference*		pDepthStencilAttachment
211 		0u,																						// deUint32							preserveAttachmentCount
212 		DE_NULL																					// const deUint32*					pPreserveAttachments
213 	};
214 
215 	const VkRenderPassCreateInfo				renderPassInfo			=
216 	{
217 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType
218 		DE_NULL,									// const void*						pNext
219 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
220 		deUint32(attachmentDescriptions.size()),	// deUint32							attachmentCount
221 		attachmentDescriptions.data(),				// const VkAttachmentDescription*	pAttachments
222 		1u,											// deUint32							subpassCount
223 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses
224 		0u,											// deUint32							dependencyCount
225 		DE_NULL																		// const VkSubpassDependency*		pDependencies
226 	};
227 
228 	return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
229 }
230 
231 class TransientAttachmentTest : public TestCase
232 {
233 public:
234 						TransientAttachmentTest	(tcu::TestContext&				testCtx,
235 												 const std::string				name,
236 												 const TestMode					testMode,
237 												 const VkMemoryPropertyFlags	flags,
238 												 const tcu::IVec2				renderSize);
239 
240 	void				initPrograms			(SourceCollections&				programCollection) const;
241 	TestInstance*		createInstance			(Context&						context) const;
242 	virtual void		checkSupport			(Context&						context) const;
243 
244 private:
245 	const TestMode					m_testMode;
246 	const VkMemoryPropertyFlags		m_flags;
247 	const tcu::IVec2				m_renderSize;
248 };
249 
TransientAttachmentTest(tcu::TestContext & testCtx,const std::string name,const TestMode testMode,const VkMemoryPropertyFlags flags,const tcu::IVec2 renderSize)250 TransientAttachmentTest::TransientAttachmentTest (
251 	tcu::TestContext&			testCtx,
252 	const std::string			name,
253 	const TestMode				testMode,
254 	const VkMemoryPropertyFlags	flags,
255 	const tcu::IVec2			renderSize)
256 	: TestCase		(testCtx, name, "")
257 	, m_testMode	(testMode)
258 	, m_flags		(flags)
259 	, m_renderSize	(renderSize)
260 {
261 }
262 
initPrograms(SourceCollections & programCollection) const263 void TransientAttachmentTest::initPrograms (SourceCollections& programCollection) const
264 {
265 	// Vertex shader
266 	{
267 		std::ostringstream src;
268 
269 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
270 			<< "\n"
271 			<< "layout(location = 0) in vec4 position;\n"
272 			<< "\n"
273 			<< "out gl_PerVertex\n"
274 			<< "{\n"
275 			<< "   vec4 gl_Position;\n"
276 			<< "};\n"
277 			<< "\n"
278 			<< "void main (void)\n"
279 			<< "{\n"
280 			<< "    gl_Position = position;\n"
281 			<< "}\n";
282 
283 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
284 	}
285 
286 	// Fragment shader
287 	{
288 		std::ostringstream src;
289 
290 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
291 			<< "\n"
292 			<< "layout(input_attachment_index = 0, binding = 0) uniform "	<< (m_testMode == TestMode::MODE_STENCIL	? "usubpassInput " : "subpassInput ") << "inputValue;\n"
293 			<< "\n"
294 			<< "layout(location = 0) out vec4 fragColor;\n"
295 			<< "\n"
296 			<< "void main (void)\n"
297 			<< "{\n"
298 			<< "	fragColor = " << (m_testMode == TestMode::MODE_COLOR					? "subpassLoad(inputValue);\n"
299 													: m_testMode == TestMode::MODE_DEPTH	? "vec4(subpassLoad(inputValue).r, 0.0, 0.0, 1.0);\n"
300 													: /*			TestMode::MODE_STENCIL	*/"vec4(0.0, 0.0, float(subpassLoad(inputValue).r) / 256.0, 1.0);\n")
301 			<< "}\n";
302 
303 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
304 	}
305 }
306 
checkSupport(Context & context) const307 void TransientAttachmentTest::checkSupport (Context& context) const
308 {
309 	const InstanceInterface&				vki					= context.getInstanceInterface();
310 	const VkPhysicalDevice					physicalDevice		= context.getPhysicalDevice();
311 	VkImageFormatProperties					formatProperties;
312 	const VkPhysicalDeviceMemoryProperties	pMemoryProperties	= getPhysicalDeviceMemoryProperties(vki,physicalDevice);
313 	const std::vector<deUint32>				memoryTypeIndices	= getMemoryTypeIndices(m_flags, pMemoryProperties);
314 
315 	const VkFormat							testFormat			= m_testMode == TestMode::MODE_DEPTH
316 																? VK_FORMAT_D16_UNORM
317 																: m_testMode == TestMode::MODE_STENCIL
318 																? getSupportedStencilFormat(context.getPhysicalDevice(), context.getInstanceInterface())
319 																: VK_FORMAT_R8G8B8A8_UNORM;
320 
321 	if (memoryTypeIndices.empty())
322 	{
323 		TCU_THROW(NotSupportedError, std::string(memoryPropertyFlagBitToString(m_flags)) + " is not supported by any memory type");
324 	}
325 
326 	vki.getPhysicalDeviceImageFormatProperties	(physicalDevice, testFormat,
327 												 VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
328 												 (m_testMode == TestMode::MODE_DEPTH || m_testMode == TestMode::MODE_STENCIL)
329 												? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT	| VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT
330 												: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT			| VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
331 												 0u, &formatProperties);
332 
333 	if (formatProperties.sampleCounts == 0 || testFormat == VK_FORMAT_UNDEFINED)
334 		TCU_THROW(NotSupportedError, de::toString(testFormat) + " not supported");
335 }
336 
337 class TransientAttachmentTestInstance : public TestInstance
338 {
339 public:
340 					TransientAttachmentTestInstance	(Context&						context,
341 													 const TestMode					testMode,
342 													 const VkMemoryPropertyFlags	flags,
343 													 const tcu::IVec2				renderSize);
344 
345 	tcu::TestStatus	iterate							(void);
346 
347 private:
348 	const TestMode				m_testMode;
349 	const tcu::IVec2			m_renderSize;
350 	const VkImageAspectFlags	m_aspectFlags;
351 	const VkImageUsageFlags		m_usageFlags;
352 	const VkFormat				m_testFormat;
353 	const vk::MemoryRequirement	m_memReq;
354 };
355 
TransientAttachmentTestInstance(Context & context,const TestMode testMode,const VkMemoryPropertyFlags flags,const tcu::IVec2 renderSize)356 TransientAttachmentTestInstance::TransientAttachmentTestInstance (Context& context, const TestMode testMode, const VkMemoryPropertyFlags flags, const tcu::IVec2 renderSize)
357 	: TestInstance	(context)
358 	, m_testMode	(testMode)
359 	, m_renderSize	(renderSize)
360 	, m_aspectFlags	(	testMode	==	TestMode::MODE_DEPTH			?	VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT
361 					:	testMode	==	TestMode::MODE_STENCIL			?	VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT
362 					:														VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT)
363 	, m_usageFlags	(	testMode	==	TestMode::MODE_COLOR			?	VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT			| VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
364 					:														VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT	| VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
365 	, m_testFormat	(	testMode	==	TestMode::MODE_DEPTH			?	VK_FORMAT_D16_UNORM
366 					:	testMode	==	TestMode::MODE_STENCIL			?	getSupportedStencilFormat(m_context.getPhysicalDevice(), m_context.getInstanceInterface())
367 					:														VK_FORMAT_R8G8B8A8_UNORM)
368 	, m_memReq		(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
369 																		?	MemoryRequirement::LazilyAllocated
370 																		:	MemoryRequirement::Local)
371 {
372 	DE_ASSERT(m_testMode != TestMode::MODE_INVALID);
373 }
374 
iterate(void)375 tcu::TestStatus	TransientAttachmentTestInstance::iterate (void)
376 {
377 	const DeviceInterface&				vk							= m_context.getDeviceInterface();
378 	const VkDevice						device						= m_context.getDevice();
379 	const VkQueue						queue						= m_context.getUniversalQueue();
380 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
381 	Allocator&							allocator					= m_context.getDefaultAllocator();
382 	const VkImageSubresourceRange		testSubresourceRange		= makeImageSubresourceRange(m_aspectFlags, 0u, 1u, 0u, 1u);
383 	const VkFormat						outputFormat				= VK_FORMAT_R8G8B8A8_UNORM;
384 	const VkImageAspectFlags			outputAspectFlags			= VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT;
385 	const VkImageUsageFlags				outputUsageFlags			= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
386 
387 	// Test attachment
388 	const Unique<VkImage>				inputImage					(makeImage(vk, device, makeImageCreateInfo(m_testFormat, m_renderSize, m_usageFlags)));
389 	const UniquePtr<Allocation>			inputImageAllocator			(bindImage(vk, device, allocator, *inputImage, m_memReq));
390 	const Unique<VkImageView>			inputImageView				(makeImageView(vk, device, *inputImage, VK_IMAGE_VIEW_TYPE_2D, m_testFormat, testSubresourceRange));
391 	const VkImageView					firstAttachmentImages[]		= { *inputImageView };
392 
393 	const VkImageSubresourceRange		outputSubresourceRange		= makeImageSubresourceRange(outputAspectFlags, 0u, 1u, 0u, 1u);
394 	const Unique<VkImage>				outputImage					(makeImage(vk, device, makeImageCreateInfo(outputFormat, m_renderSize, outputUsageFlags)));
395 	const UniquePtr<Allocation>			outputImageAllocator		(bindImage(vk, device, allocator, *outputImage, MemoryRequirement::Local));
396 	const Unique<VkImageView>			outputImageView				(makeImageView(vk, device, *outputImage, VK_IMAGE_VIEW_TYPE_2D, outputFormat, outputSubresourceRange));
397 	const VkImageView					secondAttachmentImages[]	= { *inputImageView, *outputImageView };
398 
399 	const VkDeviceSize					resultBufferSizeBytes		= tcu::getPixelSize(mapVkFormat(outputFormat)) * m_renderSize.x() * m_renderSize.y();
400 	const Unique<VkBuffer>				resultBuffer				(makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
401 	const UniquePtr<Allocation>			resultBufferAlloc			(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
402 
403 	// Main vertex buffer
404 	const deUint32						numVertices					= 6;
405 	const VkDeviceSize					vertexBufferSizeBytes		= 256;
406 	const Unique<VkBuffer>				vertexBuffer				(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
407 	const UniquePtr<Allocation>			vertexBufferAlloc			(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
408 
409 	{
410 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
411 
412 		pVertices[0]	= tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
413 		pVertices[1]	= tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
414 		pVertices[2]	= tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f);
415 		pVertices[3]	= tcu::Vec4(-1.0f,  1.0f, 1.0f, 1.0f);
416 		pVertices[4]	= tcu::Vec4( 1.0f,  1.0f, 1.0f, 1.0f);
417 		pVertices[5]	= tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f);
418 
419 		flushAlloc(vk, device, *vertexBufferAlloc);
420 	}
421 
422 	// Shader modules
423 	const Unique<VkShaderModule>		vertexModule				(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
424 	const Unique<VkShaderModule>		fragmentModule				(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
425 
426 	// Descriptor pool and descriptor set
427 	DescriptorPoolBuilder				poolBuilder;
428 	{
429 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u);
430 	}
431 
432 	const auto							descriptorPool				= poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
433 
434 	DescriptorSetLayoutBuilder			layoutBuilderAttachments;
435 	{
436 		layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
437 	}
438 
439 	const auto							inputAttachmentsSetLayout	= layoutBuilderAttachments.build(vk, device);
440 	const auto							descriptorSetAttachments	= makeDescriptorSet(vk, device, descriptorPool.get(), inputAttachmentsSetLayout.get());
441 	const std::vector<VkDescriptorSet>	descriptorSets				= { descriptorSetAttachments.get() };
442 
443 	const VkDescriptorImageInfo			imageInfo					=
444 	{
445 		DE_NULL,									// VkSampler		sampler;
446 		*inputImageView,							// VkImageView		imageView;
447 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
448 	};
449 
450 	DescriptorSetUpdateBuilder			updater;
451 	{
452 		updater.writeSingle(descriptorSetAttachments.get(), DescriptorSetUpdateBuilder::Location::binding(static_cast<deUint32>(0)), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfo);
453 		updater.update(vk, device);
454 	}
455 
456 	const bool							isDepthStencil				= isDepthStencilFormat(m_testFormat);
457 	VkImageLayout						inputLayout					= isDepthStencil
458 																	? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
459 																	: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
460 
461 	// Renderpasses
462 	VkAttachmentDescription				clearPassAttachment			= makeAttachment(m_testFormat, VK_ATTACHMENT_LOAD_OP_CLEAR,		VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, inputLayout);
463 	VkAttachmentDescription				inputPassAttachment			= makeAttachment(m_testFormat, VK_ATTACHMENT_LOAD_OP_LOAD,		VK_ATTACHMENT_STORE_OP_STORE, inputLayout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
464 	VkAttachmentDescription				outputPassAttachment		= makeAttachment(outputFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE,	VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
465 
466 	const Unique<VkRenderPass>			renderPassOne				(makeRenderPass(vk, device, { clearPassAttachment }, false));
467 	const Unique<VkRenderPass>			renderPassTwo				(makeRenderPass(vk, device, { inputPassAttachment, outputPassAttachment }, true));
468 
469 	const Unique<VkFramebuffer>			framebufferOne				(makeFramebuffer(vk, device, *renderPassOne, 1, firstAttachmentImages, m_renderSize.x(), m_renderSize.y()));
470 	const Unique<VkFramebuffer>			framebufferTwo				(makeFramebuffer(vk, device, *renderPassTwo, 2, secondAttachmentImages, m_renderSize.x(), m_renderSize.y()));
471 
472 	// Pipeline
473 	const std::vector<VkViewport>		viewports					(1, makeViewport(m_renderSize));
474 	const std::vector<VkRect2D>			scissors					(1, makeRect2D(m_renderSize));
475 	const Unique<VkPipelineLayout>		pipelineLayout				(makePipelineLayout(vk, device, *inputAttachmentsSetLayout));
476 	const Unique<VkPipeline>			pipeline					(vk::makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
477 																							  device,								// const VkDevice								device
478 																							  *pipelineLayout,						// const VkPipelineLayout						pipelineLayout
479 																							  *vertexModule,						// const VkShaderModule							vertexShaderModule
480 																							  DE_NULL,								// const VkShaderModule							essellationControlModule
481 																							  DE_NULL,								// const VkShaderModule							tessellationEvalModule
482 																							  DE_NULL,								// const VkShaderModule							geometryShaderModule
483 																							  *fragmentModule,						// const VkShaderModule							fragmentShaderModule
484 																							  *renderPassTwo,						// const VkRenderPass							renderPass
485 																							  viewports,							// const std::vector<VkViewport>&				viewports
486 																							  scissors,								// const std::vector<VkRect2D>&					scissors
487 																							  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
488 																							  0u,									// const deUint32								subpass
489 																							  0u));									// const VkPipelineDepthStencilStateCreateInfo*	depthStencilStateCreateInfo
490 
491 	// Command buffer
492 	const Unique<VkCommandPool>			cmdPool						(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
493 	const Unique<VkCommandBuffer>		cmdBuffer					(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
494 
495 	{
496 		const VkDeviceSize	vertexBufferOffset	= 0ull;
497 		VkClearValue		clearValue;
498 
499 		if		(m_testMode == TestMode::MODE_COLOR)	clearValue.color				= { { 1.0f, 1.0f, 0.0f, 1.0f } };
500 		else if	(m_testMode == TestMode::MODE_DEPTH)	clearValue.depthStencil.depth	= 0.5f;
501 		else if (m_testMode == TestMode::MODE_STENCIL)	clearValue.depthStencil			= { 0.0f, 128u };
502 
503 		const VkRect2D		renderArea			=
504 		{
505 			makeOffset2D(0, 0),
506 			makeExtent2D(m_renderSize.x(), m_renderSize.y()),
507 		};
508 
509 		beginCommandBuffer(vk, *cmdBuffer);
510 
511 		// Clear attachment
512 		beginRenderPass(vk, *cmdBuffer, *renderPassOne, *framebufferOne, renderArea, clearValue);
513 		endRenderPass(vk, *cmdBuffer);
514 
515 		// Synchronize clear and read operations.
516 		{
517 			const auto srcAccess	= isDepthStencil ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
518 			const auto dstAccess	= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
519 			const auto srcStage		= isDepthStencil ? (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT) : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
520 			const auto dstStage		= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
521 			const auto clearToLoad	= makeMemoryBarrier(srcAccess, dstAccess);
522 			cmdPipelineMemoryBarrier(vk, *cmdBuffer, srcStage, dstStage, &clearToLoad);
523 		}
524 
525 		// Draw with input attachment
526 		beginRenderPass(vk, *cmdBuffer, *renderPassTwo, *framebufferTwo, renderArea);
527 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
528 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
529 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, static_cast<deUint32>(descriptorSets.size()), descriptorSets.data(), 0u, nullptr);
530 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
531 		endRenderPass(vk, *cmdBuffer);
532 
533 		copyImageToBuffer(vk, *cmdBuffer, *outputImage, *resultBuffer, m_renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, outputPassAttachment.finalLayout, 1u, outputAspectFlags, outputAspectFlags);
534 
535 		endCommandBuffer(vk, *cmdBuffer);
536 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
537 	}
538 
539 	// Verify results
540 	{
541 		invalidateAlloc(vk, device, *resultBufferAlloc);
542 
543 		const tcu::ConstPixelBufferAccess	imagePixelAccess(mapVkFormat(outputFormat), m_renderSize.x(), m_renderSize.y(), 1, resultBufferAlloc->getHostPtr());
544 		tcu::TextureLevel					referenceImage(mapVkFormat(outputFormat), m_renderSize.x(), m_renderSize.y());
545 		const tcu::Vec4						clearColor	= m_testMode == TestMode::MODE_COLOR
546 														? tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f)
547 														: m_testMode == TestMode::MODE_DEPTH ? tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f)
548 														: tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f);
549 
550 		tcu::clear(referenceImage.getAccess(), clearColor);
551 
552 		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
553 		{
554 			return tcu::TestStatus::fail("Rendered color image is not correct");
555 		}
556 	}
557 
558 	return tcu::TestStatus::pass("Success");
559 }
560 
createInstance(Context & context) const561 TestInstance* TransientAttachmentTest::createInstance (Context& context) const
562 {
563 	return new TransientAttachmentTestInstance(context, m_testMode, m_flags, m_renderSize);
564 }
565 
566 } // anonymous
567 
createTransientAttachmentTests(tcu::TestContext & testCtx)568 tcu::TestCaseGroup* createTransientAttachmentTests(tcu::TestContext& testCtx)
569 {
570 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "transient_attachment_bit", "image usage transient attachment bit load and store op test"));
571 
572 	{
573 		static const struct
574 		{
575 			std::string					caseName;
576 			TestMode					testMode;
577 			const VkMemoryPropertyFlags	flags;
578 		} cases[] =
579 		{
580 			{ "color_load_store_op_test_lazy_bit",		TestMode::MODE_COLOR	,	VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT},
581 			{ "depth_load_store_op_test_lazy_bit",		TestMode::MODE_DEPTH	,	VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT},
582 			{ "stencil_load_store_op_test_lazy_bit",	TestMode::MODE_STENCIL	,	VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT},
583 			{ "color_load_store_op_test_local_bit",		TestMode::MODE_COLOR	,	VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT},
584 			{ "depth_load_store_op_test_local_bit",		TestMode::MODE_DEPTH	,	VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT},
585 			{ "stencil_load_store_op_test_local_bit",	TestMode::MODE_STENCIL	,	VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT}
586 		};
587 
588 		for (const auto& testCase: cases)
589 		{
590 			testGroup->addChild(new TransientAttachmentTest(testCtx, testCase.caseName, testCase.testMode, testCase.flags, tcu::IVec2(32, 32)));
591 		}
592 	}
593 
594 	return testGroup.release();
595 }
596 
597 } // FragmentOperations
598 } // vkt
599