1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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 Protected memory attachment clear tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktProtectedMemAttachmentClearTests.hpp"
26 
27 #include "deRandom.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuVector.hpp"
30 
31 #include "vkPrograms.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestGroupUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 
38 #include "vktProtectedMemContext.hpp"
39 #include "vktProtectedMemUtils.hpp"
40 #include "vktProtectedMemImageValidator.hpp"
41 
42 namespace vkt
43 {
44 namespace ProtectedMem
45 {
46 
47 namespace
48 {
49 
50 enum {
51 	RENDER_WIDTH	= 128,
52 	RENDER_HEIGHT	= 128,
53 };
54 
55 class AttachmentClearTestInstance : public ProtectedTestInstance
56 {
57 public:
58 								AttachmentClearTestInstance	(Context&					ctx,
59 															 const vk::VkClearValue&	clearValue,
60 															 const ValidationData&		refData,
61 															 const ImageValidator&		validator,
62 															 const CmdBufferType		cmdBufferType);
63 	virtual tcu::TestStatus		iterate						(void);
64 
65 private:
66 	const vk::VkFormat			m_imageFormat;
67 	const vk::VkClearValue&		m_clearValue;
68 	const ValidationData&		m_refData;
69 	const ImageValidator&		m_validator;
70 	const CmdBufferType			m_cmdBufferType;
71 };
72 
73 
74 class AttachmentClearTestCase : public TestCase
75 {
76 public:
AttachmentClearTestCase(tcu::TestContext & testCtx,const std::string & name,vk::VkClearValue clearValue,ValidationData data,CmdBufferType cmdBufferType)77 							AttachmentClearTestCase		(tcu::TestContext&		testCtx,
78 														 const std::string&		name,
79 														 vk::VkClearValue		clearValue,
80 														 ValidationData			data,
81 														 CmdBufferType			cmdBufferType)
82 								: TestCase			(testCtx, name, "Clear attachment.")
83 								, m_clearValue		(clearValue)
84 								, m_refData			(data)
85 								, m_cmdBufferType	(cmdBufferType)
86 							{
87 							}
88 
~AttachmentClearTestCase(void)89 	virtual					~AttachmentClearTestCase	(void) {}
createInstance(Context & ctx) const90 	virtual TestInstance*	createInstance				(Context& ctx) const
91 							{
92 								return new AttachmentClearTestInstance(ctx, m_clearValue, m_refData, m_validator, m_cmdBufferType);
93 							}
initPrograms(vk::SourceCollections & programCollection) const94 	virtual void			initPrograms				(vk::SourceCollections&	programCollection) const
95 							{
96 								m_validator.initPrograms(programCollection);
97 							}
98 private:
99 	vk::VkClearValue		m_clearValue;
100 	ValidationData			m_refData;
101 	ImageValidator			m_validator;
102 	CmdBufferType			m_cmdBufferType;
103 };
104 
AttachmentClearTestInstance(Context & ctx,const vk::VkClearValue & clearValue,const ValidationData & refData,const ImageValidator & validator,const CmdBufferType cmdBufferType)105 AttachmentClearTestInstance::AttachmentClearTestInstance	(Context&					ctx,
106 															 const vk::VkClearValue&	clearValue,
107 															 const ValidationData&		refData,
108 															 const ImageValidator&		validator,
109 															 const CmdBufferType		cmdBufferType)
110 	: ProtectedTestInstance	(ctx)
111 	, m_imageFormat			(vk::VK_FORMAT_R8G8B8A8_UNORM)
112 	, m_clearValue			(clearValue)
113 	, m_refData				(refData)
114 	, m_validator			(validator)
115 	, m_cmdBufferType		(cmdBufferType)
116 {
117 }
118 
iterate()119 tcu::TestStatus AttachmentClearTestInstance::iterate()
120 {
121 	ProtectedContext&					ctx					(m_protectedContext);
122 	const vk::DeviceInterface&			vk					= ctx.getDeviceInterface();
123 	const vk::VkDevice					device				= ctx.getDevice();
124 	const vk::VkQueue					queue				= ctx.getQueue();
125 	const deUint32						queueFamilyIndex	= ctx.getQueueFamilyIndex();
126 
127 	// Create output image
128 	de::MovePtr<vk::ImageWithMemory>	colorImage			(createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
129 																			RENDER_WIDTH, RENDER_HEIGHT,
130 																			m_imageFormat,
131 																			vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_SAMPLED_BIT));
132 	vk::Unique<vk::VkImageView>			colorImageView		(createImageView(ctx, **colorImage, m_imageFormat));
133 
134 	vk::Unique<vk::VkRenderPass>		renderPass			(createRenderPass(ctx, m_imageFormat));
135 	vk::Unique<vk::VkFramebuffer>		framebuffer			(createFramebuffer(ctx, RENDER_WIDTH, RENDER_HEIGHT, *renderPass, *colorImageView));
136 	vk::Unique<vk::VkPipelineLayout>	pipelineLayout		(createPipelineLayout(ctx, 0u, DE_NULL));
137 
138 	vk::Unique<vk::VkCommandPool>		cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
139 	vk::Unique<vk::VkCommandBuffer>		cmdBuffer			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
140 	vk::Unique<vk::VkCommandBuffer>		secondaryCmdBuffer	(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
141 	vk::VkCommandBuffer					targetCmdBuffer		= (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
142 
143 	// Begin cmd buffer
144 	beginCommandBuffer(vk, *cmdBuffer);
145 
146 	// Start image barrier
147 	{
148 		const vk::VkImageMemoryBarrier	startImgBarrier		=
149 		{
150 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// sType
151 			DE_NULL,											// pNext
152 			0,													// srcAccessMask
153 			vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// dstAccessMask
154 			vk::VK_IMAGE_LAYOUT_UNDEFINED,						// oldLayout
155 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// newLayout
156 			queueFamilyIndex,									// srcQueueFamilyIndex
157 			queueFamilyIndex,									// dstQueueFamilyIndex
158 			**colorImage,										// image
159 			{
160 				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
161 				0u,												// baseMipLevel
162 				1u,												// mipLevels
163 				0u,												// baseArraySlice
164 				1u,												// subresourceRange
165 			}
166 		};
167 
168 		vk.cmdPipelineBarrier(*cmdBuffer,
169 							  vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
170 							  vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
171 							  (vk::VkDependencyFlags)0,
172 							  0, (const vk::VkMemoryBarrier*)DE_NULL,
173 							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
174 							  1, &startImgBarrier);
175 	}
176 
177 	// Image clear to different from input color
178 
179 	const tcu::Vec4						clearValue			(m_clearValue.color.float32[0] < 0.5f ? 1.0f : 0.0f,
180 															 m_clearValue.color.float32[1] < 0.5f ? 1.0f : 0.0f,
181 															 m_clearValue.color.float32[2] < 0.5f ? 1.0f : 0.0f,
182 															 m_clearValue.color.float32[3] < 0.5f ? 1.0f : 0.0f);
183 
184 	const vk::VkSubpassContents			subpassContents		= m_cmdBufferType == CMD_BUFFER_SECONDARY
185 															  ? vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
186 															  : vk::VK_SUBPASS_CONTENTS_INLINE;
187 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, vk::makeRect2D(RENDER_WIDTH, RENDER_HEIGHT), clearValue, subpassContents);
188 
189 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
190 	{
191 		// Begin secondary command buffer
192 		const vk::VkCommandBufferInheritanceInfo	bufferInheritanceInfo	=
193 		{
194 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,		// sType
195 			DE_NULL,													// pNext
196 			*renderPass,												// renderPass
197 			0u,															// subpass
198 			*framebuffer,												// framebuffer
199 			VK_FALSE,													// occlusionQueryEnable
200 			(vk::VkQueryControlFlags)0u,								// queryFlags
201 			(vk::VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
202 		};
203 		beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, bufferInheritanceInfo);
204 	}
205 
206 	{
207 		const vk::VkClearAttachment		pAttachments		=
208 		{
209 			vk::VK_IMAGE_ASPECT_COLOR_BIT,						//VkImageAspectFlags	aspectMask
210 			0u,													//uint32_t				colorAttachment
211 			m_clearValue										// VkClearValue			clearValue;
212 		};
213 		const vk::VkRect2D				rect2D				= vk::makeRect2D(RENDER_WIDTH, RENDER_HEIGHT);
214 		const vk::VkClearRect			clearRect			=
215 		{
216 			rect2D,												// VkRect2D				rect;
217 			0u,													// deUint32				baseArrayLayer;
218 			1u													// deUint32				layerCount;
219 		};
220 		vk.cmdClearAttachments(targetCmdBuffer, 1u, &pAttachments, 1u, &clearRect);
221 	}
222 
223 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
224 	{
225 		endCommandBuffer(vk, *secondaryCmdBuffer);
226 		vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
227 	}
228 
229 	endRenderPass(vk, *cmdBuffer);
230 
231 	{
232 		// Image validator reads image in compute shader
233 		const vk::VkImageMemoryBarrier	endImgBarrier		=
234 		{
235 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// sType
236 			DE_NULL,											// pNext
237 			vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// srcAccessMask
238 			vk::VK_ACCESS_SHADER_READ_BIT,						// dstAccessMask
239 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// oldLayout
240 			vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,		// newLayout
241 			queueFamilyIndex,									// srcQueueFamilyIndex
242 			queueFamilyIndex,									// dstQueueFamilyIndex
243 			**colorImage,										// image
244 			{
245 				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
246 				0u,												// baseMipLevel
247 				1u,												// mipLevels
248 				0u,												// baseArraySlice
249 				1u,												// subresourceRange
250 			}
251 		};
252 		vk.cmdPipelineBarrier(*cmdBuffer,
253 							  vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
254 							  vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
255 							  (vk::VkDependencyFlags)0,
256 							  0, (const vk::VkMemoryBarrier*)DE_NULL,
257 							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
258 							  1, &endImgBarrier);
259 	}
260 
261 	endCommandBuffer(vk, *cmdBuffer);
262 
263 	// Submit command buffer
264 	const vk::Unique<vk::VkFence>	fence		(vk::createFence(vk, device));
265 	VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
266 
267 	// Log out test data
268 	ctx.getTestContext().getLog()
269 		<< tcu::TestLog::Message << "Color clear value: " << tcu::Vec4(m_clearValue.color.float32) << tcu::TestLog::EndMessage
270 		<< tcu::TestLog::Message << "Depth clear value: " << m_clearValue.depthStencil.depth << tcu::TestLog::EndMessage
271 		<< tcu::TestLog::Message << "Stencil clear value: " << m_clearValue.depthStencil.stencil << tcu::TestLog::EndMessage;
272 
273 	// Validate resulting image
274 	if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
275 		return tcu::TestStatus::pass("Everything went OK");
276 	else
277 		return tcu::TestStatus::fail("Something went really wrong");
278 }
279 
createAttachmentClearTests(tcu::TestContext & testCtx,CmdBufferType cmdBufferType)280 tcu::TestCaseGroup*	createAttachmentClearTests (tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
281 {
282 	struct {
283 		const vk::VkClearValue		clearValue;
284 		const ValidationData		data;
285 	} testData[] = {
286 		{	vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f),
287 			{
288 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
289 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
290 				{ tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
291 				  tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
292 			}
293 		},
294 		{	vk::makeClearValueColorF32(0.0f, 1.0f, 0.0f, 1.0f),
295 			{
296 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
297 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
298 				{ tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
299 				  tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), }
300 			}
301 		},
302 		{	vk::makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f),
303 			{
304 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
305 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
306 				{ tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
307 				  tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), }
308 			}
309 		},
310 		{	vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f),
311 			{
312 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
313 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
314 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
315 				  tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), }
316 			}
317 		},
318 		{	vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f),
319 			{
320 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
321 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
322 				{ tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
323 				  tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
324 			}
325 		},
326 		{	vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 0.0f),
327 			{
328 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
329 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
330 				{ tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
331 				  tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), }
332 			}
333 		},
334 		{	vk::makeClearValueColorF32(0.1f, 0.2f, 0.3f, 0.0f),
335 			{
336 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
337 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
338 				{ tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
339 				  tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), }
340 			}
341 		},
342 	};
343 
344 	de::MovePtr<tcu::TestCaseGroup>	clearStaticTests	(new tcu::TestCaseGroup(testCtx, "static", "Attachment Clear Op Tests with static input"));
345 
346 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
347 	{
348 		const std::string name = "clear_" +  de::toString(ndx + 1);
349 		clearStaticTests->addChild(new AttachmentClearTestCase(testCtx, name.c_str(), testData[ndx].clearValue, testData[ndx].data, cmdBufferType));
350 	}
351 
352 	/* Add a few randomized tests */
353 	de::MovePtr<tcu::TestCaseGroup>	clearRandomTests	(new tcu::TestCaseGroup(testCtx, "random", "Attachment Clear Op Tests with random input"));
354 	const int						testCount			= 10;
355 	de::Random						rnd					(testCtx.getCommandLine().getBaseSeed());
356 	for (int ndx = 0; ndx < testCount; ++ndx)
357 	{
358 		const std::string	name		= "clear_" +  de::toString(ndx + 1);
359 		vk::VkClearValue	clearValue	= vk::makeClearValueColorF32(
360 											rnd.getFloat(0.0, 1.0f),
361 											rnd.getFloat(0.0, 1.0f),
362 											rnd.getFloat(0.0, 1.0f),
363 											rnd.getFloat(0.0, 1.0f));
364 
365 		tcu::Vec4			refValue	(clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]);
366 		ValidationData		data		=
367 		{
368 			{ tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)),
369 			  tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)),
370 			  tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)),
371 			  tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)) },
372 			{ refValue, refValue, refValue, refValue }
373 		};
374 
375 		clearRandomTests->addChild(new AttachmentClearTestCase(testCtx, name.c_str(), clearValue, data, cmdBufferType));
376 	}
377 
378 	std::string groupName = getCmdBufferTypeStr(cmdBufferType);
379 	std::string groupDesc = "Attachment Clear Op Tests with " + groupName + " command buffer";
380 	de::MovePtr<tcu::TestCaseGroup> clearTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
381 	clearTests->addChild(clearStaticTests.release());
382 	clearTests->addChild(clearRandomTests.release());
383 	return clearTests.release();
384 }
385 
386 } // anonymous
387 
createAttachmentClearTests(tcu::TestContext & testCtx)388 tcu::TestCaseGroup*	createAttachmentClearTests (tcu::TestContext& testCtx)
389 {
390 	de::MovePtr<tcu::TestCaseGroup> clearTests (new tcu::TestCaseGroup(testCtx, "clear_op", "Attachment Clear Op Tests"));
391 
392 	clearTests->addChild(createAttachmentClearTests(testCtx, CMD_BUFFER_PRIMARY));
393 	clearTests->addChild(createAttachmentClearTests(testCtx, CMD_BUFFER_SECONDARY));
394 
395 	return clearTests.release();
396 }
397 
398 } // ProtectedMem
399 } // vkt
400