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 content clear color image tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktProtectedMemClearColorImageTests.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 ClearColorImageTestInstance : public ProtectedTestInstance
56 {
57 public:
58 										ClearColorImageTestInstance	(Context&						ctx,
59 																	 const vk::VkClearColorValue&	clearColorValue,
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::VkClearColorValue&		m_clearColorValue;
68 	const ValidationData&				m_refData;
69 	const ImageValidator&				m_validator;
70 	const CmdBufferType					m_cmdBufferType;
71 };
72 
73 class ClearColorImageTestCase : public TestCase
74 {
75 public:
ClearColorImageTestCase(tcu::TestContext & testCtx,const std::string & name,vk::VkClearColorValue clearColorValue,ValidationData data,CmdBufferType cmdBufferType)76 								ClearColorImageTestCase		(tcu::TestContext&			testCtx,
77 															 const std::string&			name,
78 															 vk::VkClearColorValue		clearColorValue,
79 															 ValidationData				data,
80 															 CmdBufferType				cmdBufferType)
81 									: TestCase				(testCtx, name, "Clear color image.")
82 									, m_clearColorValue		(clearColorValue)
83 									, m_refData				(data)
84 									, m_cmdBufferType		(cmdBufferType)
85 								{
86 								}
87 
~ClearColorImageTestCase(void)88 	virtual						~ClearColorImageTestCase	(void) {}
createInstance(Context & ctx) const89 	virtual TestInstance*		createInstance				(Context& ctx) const
90 								{
91 									return new ClearColorImageTestInstance(ctx, m_clearColorValue, m_refData, m_validator, m_cmdBufferType);
92 								}
initPrograms(vk::SourceCollections & programCollection) const93 	virtual void				initPrograms				(vk::SourceCollections& programCollection) const
94 								{
95 									m_validator.initPrograms(programCollection);
96 								}
97 private:
98 	vk::VkClearColorValue		m_clearColorValue;
99 	ValidationData				m_refData;
100 	ImageValidator				m_validator;
101 	CmdBufferType				m_cmdBufferType;
102 };
103 
ClearColorImageTestInstance(Context & ctx,const vk::VkClearColorValue & clearColorValue,const ValidationData & refData,const ImageValidator & validator,const CmdBufferType cmdBufferType)104 ClearColorImageTestInstance::ClearColorImageTestInstance	(Context&						ctx,
105 															 const vk::VkClearColorValue&	clearColorValue,
106 															 const ValidationData&			refData,
107 															 const ImageValidator&			validator,
108 															 const CmdBufferType			cmdBufferType)
109 	: ProtectedTestInstance		(ctx)
110 	, m_imageFormat				(vk::VK_FORMAT_R8G8B8A8_UNORM)
111 	, m_clearColorValue			(clearColorValue)
112 	, m_refData					(refData)
113 	, m_validator				(validator)
114 	, m_cmdBufferType			(cmdBufferType)
115 {
116 }
117 
iterate()118 tcu::TestStatus ClearColorImageTestInstance::iterate()
119 {
120 	ProtectedContext&					ctx					(m_protectedContext);
121 	const vk::DeviceInterface&			vk					= ctx.getDeviceInterface();
122 	const vk::VkDevice					device				= ctx.getDevice();
123 	const vk::VkQueue					queue				= ctx.getQueue();
124 	const deUint32						queueFamilyIndex	= ctx.getQueueFamilyIndex();
125 
126 	// Create output image
127 	de::MovePtr<vk::ImageWithMemory>	colorImage			= createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
128 																			RENDER_WIDTH, RENDER_HEIGHT,
129 																			vk::VK_FORMAT_R8G8B8A8_UNORM,
130 																			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_SAMPLED_BIT);
131 
132 	vk::Unique<vk::VkPipelineLayout>	pipelineLayout		(createPipelineLayout(ctx, 0u, DE_NULL));
133 
134 	vk::Unique<vk::VkCommandPool>		cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
135 	vk::Unique<vk::VkCommandBuffer>		cmdBuffer			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
136 	vk::Unique<vk::VkCommandBuffer>		secondaryCmdBuffer	(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
137 	vk::VkCommandBuffer					targetCmdBuffer		= (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
138 
139 	const vk::VkImageSubresourceRange subresourceRange =
140 	{
141 		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
142 		0u,								// uint32_t				baseMipLevel
143 		1u,								// uint32_t				levelCount
144 		0u,								// uint32_t				baseArrayLayer
145 		1u,								// uint32_t				layerCount
146 	};
147 	// Begin cmd buffer
148 	beginCommandBuffer(vk, *cmdBuffer);
149 
150 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
151 	{
152 		// Begin secondary command buffer
153 		const vk::VkCommandBufferInheritanceInfo	bufferInheritanceInfo	=
154 		{
155 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,		// sType
156 			DE_NULL,													// pNext
157 			DE_NULL,													// renderPass
158 			0u,															// subpass
159 			DE_NULL,													// framebuffer
160 			VK_FALSE,													// occlusionQueryEnable
161 			(vk::VkQueryControlFlags)0u,								// queryFlags
162 			(vk::VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
163 		};
164 		beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, bufferInheritanceInfo);
165 	}
166 
167 	// Start image barrier
168 	{
169 		const vk::VkImageMemoryBarrier	initializeBarrier	=
170 		{
171 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// sType
172 			DE_NULL,											// pNext
173 			0,													// srcAccessMask
174 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// dstAccessMask
175 			vk::VK_IMAGE_LAYOUT_UNDEFINED,						// oldLayout
176 			vk::VK_IMAGE_LAYOUT_GENERAL,						// newLayout
177 			queueFamilyIndex,									// srcQueueFamilyIndex
178 			queueFamilyIndex,									// dstQueueFamilyIndex
179 			**colorImage,										// image
180 			subresourceRange,									// subresourceRange
181 		};
182 
183 		vk.cmdPipelineBarrier(targetCmdBuffer,								// commandBuffer
184 							  vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,		// srcStageMask
185 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,			// dstStageMask
186 							  (vk::VkDependencyFlags)0,						// dependencyFlags
187 							  0, (const vk::VkMemoryBarrier*)DE_NULL,		// memoryBarrierCount, pMemoryBarriers
188 							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,	// bufferMemoryBarrierCount, pBufferMemoryBarriers
189 							  1, &initializeBarrier);						// imageMemoryBarrierCount, pImageMemoryBarriers
190 	}
191 
192 	// Image clear
193 	vk.cmdClearColorImage(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_GENERAL, &m_clearColorValue, 1, &subresourceRange);
194 
195 	// Image barrier to change accessMask.
196 	{
197 		const vk::VkImageMemoryBarrier	initializeBarrier	=
198 		{
199 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// sType
200 			DE_NULL,											// pNext
201 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// srcAccessMask
202 			vk::VK_ACCESS_SHADER_READ_BIT,						// dstAccessMask
203 			vk::VK_IMAGE_LAYOUT_GENERAL,						// oldLayout
204 			vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,		// newLayout
205 			queueFamilyIndex,									// srcQueueFamilyIndex
206 			queueFamilyIndex,									// dstQueueFamilyIndex
207 			**colorImage,										// image
208 			subresourceRange									// subresourceRange
209 		};
210 		vk.cmdPipelineBarrier(targetCmdBuffer,
211 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,		// srcStageMask
212 							  vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,	// dstStageMask
213 							  (vk::VkDependencyFlags)0,
214 							  0, (const vk::VkMemoryBarrier*)DE_NULL,
215 							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
216 							  1, &initializeBarrier);
217 	}
218 
219 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
220 	{
221 		endCommandBuffer(vk, *secondaryCmdBuffer);
222 		vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
223 	}
224 
225 	endCommandBuffer(vk, *cmdBuffer);
226 
227 	// Submit command buffer
228 	const vk::Unique<vk::VkFence>	fence		(vk::createFence(vk, device));
229 	VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
230 
231 	// Log out test data
232 	ctx.getTestContext().getLog()
233 		<< tcu::TestLog::Message << "Color clear value: " << tcu::Vec4(m_clearColorValue.float32) << tcu::TestLog::EndMessage;
234 
235 	// Validate resulting image
236 	if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
237 		return tcu::TestStatus::pass("Everything went OK");
238 	else
239 		return tcu::TestStatus::fail("Something went really wrong");
240 }
241 
createClearColorImageTests(tcu::TestContext & testCtx,CmdBufferType cmdBufferType)242 tcu::TestCaseGroup*	createClearColorImageTests (tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
243 {
244 	struct {
245 		vk::VkClearColorValue	clearColorValue;
246 		ValidationData			data;
247 	} testData[] = {
248 		{	{ { 1.0f, 0.0f, 0.0f, 1.0f } },
249 			{
250 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
251 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
252 				{ tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
253 				  tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
254 			}
255 		},
256 		{	{ { 0.0f, 1.0f, 0.0f, 1.0f } },
257 			{
258 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
259 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
260 				{ tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
261 				  tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), }
262 			}
263 		},
264 		{	{ { 0.0f, 0.0f, 1.0f, 1.0f } },
265 			{
266 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
267 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
268 				{ tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
269 				  tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), }
270 			}
271 		},
272 		{	{ { 0.0f, 0.0f, 0.0f, 1.0f } },
273 			{
274 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
275 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
276 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
277 				  tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), }
278 			}
279 		},
280 		{	{ { 1.0f, 0.0f, 0.0f, 1.0f } },
281 			{
282 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
283 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
284 				{ tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
285 				  tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
286 			}
287 		},
288 		{	{ { 1.0f, 0.0f, 0.0f, 0.0f } },
289 			{
290 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
291 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
292 				{ tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
293 				  tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), }
294 			}
295 		},
296 		{	{ { 0.1f, 0.2f, 0.3f, 0.0f } },
297 			{
298 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
299 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
300 				{ tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
301 				  tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), }
302 			}
303 		},
304 	};
305 
306 	de::MovePtr<tcu::TestCaseGroup>	clearStaticTests	(new tcu::TestCaseGroup(testCtx, "static", "Clear Color Image Tests with static input"));
307 
308 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
309 	{
310 		const std::string name = "clear_" + de::toString(ndx + 1);
311 		clearStaticTests->addChild(new ClearColorImageTestCase(testCtx, name.c_str(), testData[ndx].clearColorValue, testData[ndx].data, cmdBufferType));
312 	}
313 
314 	/* Add a few randomized tests */
315 	de::MovePtr<tcu::TestCaseGroup>	clearRandomTests	(new tcu::TestCaseGroup(testCtx, "random", "Clear Color Image Tests with random input"));
316 	const int						testCount			= 10;
317 	de::Random						rnd					(testCtx.getCommandLine().getBaseSeed());
318 	for (int ndx = 0; ndx < testCount; ++ndx)
319 	{
320 		const std::string	name		= "clear_" + de::toString(ndx + 1);
321 		vk::VkClearValue	clearValue	= vk::makeClearValueColorF32(
322 											rnd.getFloat(0.0, 1.0f),
323 											rnd.getFloat(0.0, 1.0f),
324 											rnd.getFloat(0.0, 1.0f),
325 											rnd.getFloat(0.0, 1.0f));
326 
327 		tcu::Vec4			refValue	(clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]);
328 		ValidationData		data		=
329 		{
330 			{ 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)),
331 			  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)),
332 			  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)),
333 			  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)) },
334 			{ refValue, refValue, refValue, refValue }
335 		};
336 		clearRandomTests->addChild(new ClearColorImageTestCase(testCtx, name.c_str(), clearValue.color, data, cmdBufferType));
337 	}
338 
339 	std::string groupName = getCmdBufferTypeStr(cmdBufferType);
340 	std::string groupDesc = "Clear Color Image Tests with " + groupName + " command buffer";
341 	de::MovePtr<tcu::TestCaseGroup> clearTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
342 	clearTests->addChild(clearStaticTests.release());
343 	clearTests->addChild(clearRandomTests.release());
344 	return clearTests.release();
345 }
346 
347 } // anonymous
348 
createClearColorImageTests(tcu::TestContext & testCtx)349 tcu::TestCaseGroup*	createClearColorImageTests (tcu::TestContext& testCtx)
350 {
351 	de::MovePtr<tcu::TestCaseGroup> clearTests (new tcu::TestCaseGroup(testCtx, "clear_color", "Clear Color Image Tests"));
352 
353 	clearTests->addChild(createClearColorImageTests(testCtx, CMD_BUFFER_PRIMARY));
354 	clearTests->addChild(createClearColorImageTests(testCtx, CMD_BUFFER_SECONDARY));
355 
356 	return clearTests.release();
357 }
358 
359 } // ProtectedMem
360 } // vkt
361