• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 copy buffer to image tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktProtectedMemCopyBufferToImageTests.hpp"
26 
27 #include "deRandom.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuVector.hpp"
30 #include "tcuVectorUtil.hpp"
31 
32 #include "vkPrograms.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestGroupUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 
39 #include "vktProtectedMemContext.hpp"
40 #include "vktProtectedMemUtils.hpp"
41 #include "vktProtectedMemImageValidator.hpp"
42 
43 namespace vkt
44 {
45 namespace ProtectedMem
46 {
47 
48 namespace
49 {
50 
51 enum {
52 	BUFFER_SIZE		= 256,
53 	RENDER_WIDTH	= 8,
54 	RENDER_HEIGHT	= 8,
55 };
56 
57 class CopyBufferToImageTestInstance : public ProtectedTestInstance
58 {
59 public:
60 									CopyBufferToImageTestInstance	(Context&					ctx,
61 																	 const deUint32				fillValue,
62 																	 const ValidationData&		refData,
63 																	 const ImageValidator&		validator,
64 																	 const CmdBufferType		cmdBufferType);
65 virtual tcu::TestStatus				iterate							 (void);
66 
67 private:
68 	const vk::VkFormat				m_imageFormat;
69 	const deUint32					m_fillValue;
70 	const ValidationData&			m_refData;
71 	const ImageValidator&			m_validator;
72 	const CmdBufferType				m_cmdBufferType;
73 };
74 
75 class CopyBufferToImageTestCase : public TestCase
76 {
77 public:
CopyBufferToImageTestCase(tcu::TestContext & testCtx,const std::string & name,deUint32 fillValue,ValidationData data,CmdBufferType cmdBufferType)78 								CopyBufferToImageTestCase	(tcu::TestContext&			testCtx,
79 															 const std::string&			name,
80 															 deUint32					fillValue,
81 															 ValidationData				data,
82 															 CmdBufferType				cmdBufferType)
83 									: TestCase				(testCtx, name, "Copy buffer to image.")
84 									, m_fillValue			(fillValue)
85 									, m_refData				(data)
86 									, m_validator			(vk::VK_FORMAT_R32G32B32A32_SFLOAT)
87 									, m_cmdBufferType		(cmdBufferType)
88 								{
89 								}
90 
~CopyBufferToImageTestCase(void)91 	virtual						~CopyBufferToImageTestCase	(void) {}
createInstance(Context & ctx) const92 	virtual TestInstance*		createInstance				(Context& ctx) const
93 								{
94 									return new CopyBufferToImageTestInstance(ctx, m_fillValue, m_refData, m_validator, m_cmdBufferType);
95 								}
initPrograms(vk::SourceCollections & programCollection) const96 	virtual void				initPrograms				(vk::SourceCollections& programCollection) const
97 								{
98 									m_validator.initPrograms(programCollection);
99 								}
checkSupport(Context & context) const100 	virtual void				checkSupport				(Context& context) const
101 								{
102 									checkProtectedQueueSupport(context);
103 								}
104 private:
105 	deUint32					m_fillValue;
106 	ValidationData				m_refData;
107 	ImageValidator				m_validator;
108 	CmdBufferType				m_cmdBufferType;
109 };
110 
CopyBufferToImageTestInstance(Context & ctx,const deUint32 fillValue,const ValidationData & refData,const ImageValidator & validator,const CmdBufferType cmdBufferType)111 CopyBufferToImageTestInstance::CopyBufferToImageTestInstance	(Context&					ctx,
112 																 const deUint32				fillValue,
113 																 const ValidationData&		refData,
114 																 const ImageValidator&		validator,
115 																 const CmdBufferType		cmdBufferType)
116 	: ProtectedTestInstance		(ctx)
117 	, m_imageFormat				(vk::VK_FORMAT_R32G32B32A32_SFLOAT)
118 	, m_fillValue				(fillValue)
119 	, m_refData					(refData)
120 	, m_validator				(validator)
121 	, m_cmdBufferType			(cmdBufferType)
122 {
123 }
124 
iterate()125 tcu::TestStatus CopyBufferToImageTestInstance::iterate()
126 {
127 	ProtectedContext&					ctx					(m_protectedContext);
128 	const vk::DeviceInterface&			vk					= ctx.getDeviceInterface();
129 	const vk::VkDevice					device				= ctx.getDevice();
130 	const vk::VkQueue					queue				= ctx.getQueue();
131 	const deUint32						queueFamilyIndex	= ctx.getQueueFamilyIndex();
132 
133 	// Create destination image
134 	de::MovePtr<vk::ImageWithMemory>	colorImage			= createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
135 																			RENDER_WIDTH, RENDER_HEIGHT,
136 																			m_imageFormat,
137 																			vk::VK_IMAGE_USAGE_SAMPLED_BIT|vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
138 	de::MovePtr<vk::BufferWithMemory>	srcBuffer			(makeBuffer(ctx,
139 																		PROTECTION_ENABLED,
140 																		queueFamilyIndex,
141 																		(deUint32)(BUFFER_SIZE * sizeof(deUint32)),
142 																		vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
143 																			| vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT
144 																			| vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
145 																		vk::MemoryRequirement::Protected));
146 
147 	vk::Unique<vk::VkCommandPool>		cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
148 	vk::Unique<vk::VkCommandBuffer>		cmdBuffer			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
149 	vk::Unique<vk::VkCommandBuffer>		secondaryCmdBuffer	(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
150 	vk::VkCommandBuffer					targetCmdBuffer		= (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
151 
152 	// Begin cmd buffer
153 	beginCommandBuffer(vk, *cmdBuffer);
154 
155 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
156 	{
157 		// Begin secondary command buffer
158 		const vk::VkCommandBufferInheritanceInfo	bufferInheritanceInfo	=
159 		{
160 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,		// sType
161 			DE_NULL,													// pNext
162 			DE_NULL,													// renderPass
163 			0u,															// subpass
164 			DE_NULL,													// framebuffer
165 			VK_FALSE,													// occlusionQueryEnable
166 			(vk::VkQueryControlFlags)0u,								// queryFlags
167 			(vk::VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
168 		};
169 		beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, bufferInheritanceInfo);
170 	}
171 
172 	// Start src buffer barrier
173 	{
174 		const vk::VkBufferMemoryBarrier startBufferBarrier =
175 		{
176 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType		sType
177 			DE_NULL,										// const void*			pNext
178 			0,												// VkAccessFlags		srcAccessMask
179 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags		dstAccessMask
180 			queueFamilyIndex,								// uint32_t				srcQueueFamilyIndex
181 			queueFamilyIndex,								// uint32_t				dstQueueFamilyIndex
182 			**srcBuffer,									// VkBuffer				buffer
183 			0u,												// VkDeviceSize			offset
184 			VK_WHOLE_SIZE,									// VkDeviceSize			size
185 		};
186 		vk.cmdPipelineBarrier(targetCmdBuffer,
187 							  vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
188 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
189 							  (vk::VkDependencyFlags) 0,
190 							  0, (const vk::VkMemoryBarrier *) DE_NULL,
191 							  1, &startBufferBarrier,
192 							  0, (const vk::VkImageMemoryBarrier *) DE_NULL);
193 	}
194 	vk.cmdFillBuffer(targetCmdBuffer, **srcBuffer, 0u, VK_WHOLE_SIZE, m_fillValue);
195 
196 	{
197 		// Barrier to change accessMask to transfer read bit for source buffer
198 		const vk::VkBufferMemoryBarrier startCopyBufferBarrier =
199 		{
200 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType		sType
201 			DE_NULL,											// const void*			pNext
202 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		srcAccessMask
203 			vk::VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags		dstAccessMask
204 			queueFamilyIndex,									// uint32_t				srcQueueFamilyIndex
205 			queueFamilyIndex,									// uint32_t				dstQueueFamilyIndex
206 			**srcBuffer,										// VkBuffer				buffer
207 			0u,													// VkDeviceSize			offset
208 			VK_WHOLE_SIZE,										// VkDeviceSize			size
209 		};
210 
211 		// Start image barrier for destination image.
212 		const vk::VkImageMemoryBarrier	startImgBarrier		=
213 		{
214 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
215 			DE_NULL,											// const void*			pNext
216 			0,													// VkAccessFlags		srcAccessMask
217 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		dstAccessMask
218 			vk::VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout		oldLayout
219 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout		newLayout
220 			queueFamilyIndex,									// uint32_t				srcQueueFamilyIndex
221 			queueFamilyIndex,									// uint32_t				dstQueueFamilyIndex
222 			**colorImage,										// VkImage				image
223 			{
224 				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags	aspectMask
225 				0u,												// uint32_t				baseMipLevel
226 				1u,												// uint32_t				mipLevels
227 				0u,												// uint32_t				baseArraySlice
228 				1u,												// uint32_t				subresourceRange
229 			}
230 		};
231 
232 		vk.cmdPipelineBarrier(targetCmdBuffer,
233 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
234 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
235 							  (vk::VkDependencyFlags)0,
236 							  0, (const vk::VkMemoryBarrier*)DE_NULL,
237 							  1, &startCopyBufferBarrier,
238 							  1, &startImgBarrier);
239 	}
240 
241 	// Copy buffer to image
242 	const vk::VkImageSubresourceLayers	subresourceLayers	=
243 	{
244 		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags		aspectMask
245 		0u,								// uint32_t					mipLevel
246 		0u,								// uint32_t					baseArrayLayer
247 		1u,								// uint32_t					layerCount
248 	};
249 	const vk::VkOffset3D				nullOffset			= {0u, 0u, 0u};
250 	const vk::VkExtent3D				imageExtent			= {(deUint32)RENDER_WIDTH, (deUint32)RENDER_HEIGHT, 1u};
251 	const vk::VkBufferImageCopy			copyRegion			=
252 	{
253 		0ull,							// VkDeviceSize				srcOffset;
254 		0,								// uint32_t					bufferRowLength
255 		0,								// uint32_t					bufferImageHeight
256 		subresourceLayers,				// VkImageSubresourceLayers	imageSubresource
257 		nullOffset,						// VkOffset3D				imageOffset
258 		imageExtent,					// VkExtent3D				imageExtent
259 	};
260 	vk.cmdCopyBufferToImage(targetCmdBuffer, **srcBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
261 
262 	{
263 		const vk::VkImageMemoryBarrier	endImgBarrier		=
264 		{
265 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
266 			DE_NULL,											// const void*			pNext
267 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		srcAccessMask
268 			vk::VK_ACCESS_SHADER_READ_BIT,						// VkAccessFlags		dstAccessMask
269 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout		oldLayout
270 			vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,		// VkImageLayout		newLayout
271 			queueFamilyIndex,									// uint32_t				srcQueueFamilyIndex
272 			queueFamilyIndex,									// uint32_t				dstQueueFamilyIndex
273 			**colorImage,										// VkImage				image
274 			{
275 				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags	aspectMask
276 				0u,												// uint32_t				baseMipLevel
277 				1u,												// uint32_t				mipLevels
278 				0u,												// uint32_t				baseArraySlice
279 				1u,												// uint32_t				subresourceRange
280 			}
281 		};
282 		vk.cmdPipelineBarrier(targetCmdBuffer,
283 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
284 							  vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
285 							  (vk::VkDependencyFlags)0,
286 							  0, (const vk::VkMemoryBarrier*)DE_NULL,
287 							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
288 							  1, &endImgBarrier);
289 	}
290 
291 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
292 	{
293 		endCommandBuffer(vk, *secondaryCmdBuffer);
294 		vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
295 	}
296 
297 	endCommandBuffer(vk, *cmdBuffer);
298 
299 	// Submit command buffer
300 	const vk::Unique<vk::VkFence>	fence		(vk::createFence(vk, device));
301 	VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
302 
303 	// Log out test data
304 	ctx.getTestContext().getLog()
305 		<< tcu::TestLog::Message << "Fill value: " << m_fillValue << tcu::TestLog::EndMessage;
306 
307 	// Validate resulting image
308 	if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
309 		return tcu::TestStatus::pass("Everything went OK");
310 	else
311 		return tcu::TestStatus::fail("Something went really wrong");
312 }
313 
createCopyBufferToImageTests(tcu::TestContext & testCtx,CmdBufferType cmdBufferType)314 tcu::TestCaseGroup*	createCopyBufferToImageTests (tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
315 {
316 	struct {
317 		const union {
318 			float		flt;
319 			deUint32	uint;
320 		}						fillValue;
321 		const ValidationData	data;
322 	} testData[] = {
323 		{	{ 0.0f },
324 			{
325 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
326 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
327 				{ tcu::Vec4(0.0f), tcu::Vec4(0.0f),
328 				  tcu::Vec4(0.0f), tcu::Vec4(0.0f), }
329 			}
330 		},
331 		{	{ 1.0f },
332 			{
333 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
334 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
335 				{ tcu::Vec4(1.0f), tcu::Vec4(1.0f),
336 				  tcu::Vec4(1.0f), tcu::Vec4(1.0f), }
337 			}
338 		},
339 		{	{ 0.2f },
340 			{
341 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
342 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
343 				{ tcu::Vec4(0.2f), tcu::Vec4(0.2f),
344 				  tcu::Vec4(0.2f), tcu::Vec4(0.2f), }
345 			}
346 		},
347 		{	{ 0.55f },
348 			{
349 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
350 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
351 				{ tcu::Vec4(0.55f), tcu::Vec4(0.55f),
352 				  tcu::Vec4(0.55f), tcu::Vec4(0.55f), }
353 			}
354 		},
355 		{	{ 0.82f },
356 			{
357 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
358 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
359 				{ tcu::Vec4(0.82f), tcu::Vec4(0.82f),
360 				  tcu::Vec4(0.82f), tcu::Vec4(0.82f), }
361 			}
362 		},
363 		{	{ 0.96f },
364 			{
365 				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
366 				  tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
367 				{ tcu::Vec4(0.96f), tcu::Vec4(0.96f),
368 				  tcu::Vec4(0.96f), tcu::Vec4(0.96f), }
369 			}
370 		},
371 	};
372 
373 	de::MovePtr<tcu::TestCaseGroup>	copyStaticTests		(new tcu::TestCaseGroup(testCtx, "static", "Copy Buffer To Image Tests with static input"));
374 
375 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
376 	{
377 		const std::string name = "copy_" + de::toString(ndx + 1);
378 		copyStaticTests->addChild(new CopyBufferToImageTestCase(testCtx, name.c_str(), testData[ndx].fillValue.uint, testData[ndx].data, cmdBufferType));
379 	}
380 
381 	/* Add a few randomized tests */
382 	de::MovePtr<tcu::TestCaseGroup>	copyRandomTests		(new tcu::TestCaseGroup(testCtx, "random", "Copy Buffer To Image Tests with random input"));
383 	const int						testCount			= 10;
384 	de::Random						rnd					(testCtx.getCommandLine().getBaseSeed());
385 	for (int ndx = 0; ndx < testCount; ++ndx)
386 	{
387 		const std::string	name		= "copy_" + de::toString(ndx + 1);
388 
389 		const union {
390 			float		flt;
391 			deUint32	uint;
392 		}					fillValue	= { rnd.getFloat(0.0, 1.0f) };
393 
394 		const tcu::Vec4		refValue	(fillValue.flt);
395 		const tcu::Vec4		vec0		= tcu::randomVec4(rnd);
396 		const tcu::Vec4		vec1		= tcu::randomVec4(rnd);
397 		const tcu::Vec4		vec2		= tcu::randomVec4(rnd);
398 		const tcu::Vec4		vec3		= tcu::randomVec4(rnd);
399 
400 		ValidationData		data		=
401 		{
402 			{ vec0, vec1, vec2, vec3 },
403 			{ refValue, refValue, refValue, refValue }
404 		};
405 		copyRandomTests->addChild(new CopyBufferToImageTestCase(testCtx, name.c_str(), fillValue.uint, data, cmdBufferType));
406 	}
407 
408 	std::string groupName = getCmdBufferTypeStr(cmdBufferType);
409 	std::string groupDesc = "Copy Buffer To Image Tests with " + groupName + " command buffer";
410 	de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
411 	copyTests->addChild(copyStaticTests.release());
412 	copyTests->addChild(copyRandomTests.release());
413 	return copyTests.release();
414 }
415 
416 } // anonymous
417 
createCopyBufferToImageTests(tcu::TestContext & testCtx)418 tcu::TestCaseGroup*	createCopyBufferToImageTests (tcu::TestContext& testCtx)
419 {
420 	de::MovePtr<tcu::TestCaseGroup> clearTests (new tcu::TestCaseGroup(testCtx, "copy_buffer_to_image", "Copy Buffer To Image Tests"));
421 
422 	clearTests->addChild(createCopyBufferToImageTests(testCtx, CMD_BUFFER_PRIMARY));
423 	clearTests->addChild(createCopyBufferToImageTests(testCtx, CMD_BUFFER_SECONDARY));
424 
425 	return clearTests.release();
426 }
427 
428 } // ProtectedMem
429 } // vkt
430