• 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 memory copy image to buffer tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktProtectedMemCopyImageToBufferTests.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 "vktProtectedMemBufferValidator.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 	MAX_POSITION	= BUFFER_SIZE / 4,
57 };
58 
59 template<typename T>
60 class CopyImageToBufferTestInstance : public ProtectedTestInstance
61 {
62 public:
63 									CopyImageToBufferTestInstance	(Context&						ctx,
64 																	 const vk::VkClearColorValue	fillValue,
65 																	 const BufferValidator<T>&		validator,
66 																	 const CmdBufferType			cmdBufferType);
67 	virtual tcu::TestStatus			iterate							(void);
68 
69 private:
70 	const vk::VkFormat				m_imageFormat;
71 	const vk::VkClearColorValue		m_fillValue;
72 	const BufferValidator<T>&		m_validator;
73 	const CmdBufferType					m_cmdBufferType;
74 };
75 
76 
77 template<typename T>
78 class CopyImageToBufferTestCase : public TestCase
79 {
80 public:
CopyImageToBufferTestCase(tcu::TestContext & testCtx,const std::string & name,vk::VkClearColorValue fillValue,ValidationData<T> data,CmdBufferType cmdBufferType,vk::VkFormat format)81 							CopyImageToBufferTestCase	(tcu::TestContext&		testCtx,
82 														 const std::string&		name,
83 														 vk::VkClearColorValue	fillValue,
84 														 ValidationData<T>		data,
85 														 CmdBufferType			cmdBufferType,
86 														 vk::VkFormat			format)
87 								: TestCase				(testCtx, name, "Copy image to buffer.")
88 								, m_fillValue			(fillValue)
89 								, m_validator			(data, format)
90 								, m_cmdBufferType		(cmdBufferType)
91 							{
92 							}
93 
~CopyImageToBufferTestCase(void)94 	virtual					~CopyImageToBufferTestCase	(void) {}
createInstance(Context & ctx) const95 	virtual TestInstance*	createInstance				(Context& ctx) const
96 							{
97 								return new CopyImageToBufferTestInstance<T>(ctx, m_fillValue, m_validator, m_cmdBufferType);
98 							}
initPrograms(vk::SourceCollections & programCollection) const99 	virtual void			initPrograms				(vk::SourceCollections&	programCollection) const
100 							{
101 								m_validator.initPrograms(programCollection);
102 							}
checkSupport(Context & context) const103 	virtual void			checkSupport				(Context& context) const
104 							{
105 								checkProtectedQueueSupport(context);
106 							}
107 private:
108 	vk::VkClearColorValue	m_fillValue;
109 	BufferValidator<T>		m_validator;
110 	CmdBufferType			m_cmdBufferType;
111 };
112 
113 template<typename T>
CopyImageToBufferTestInstance(Context & ctx,const vk::VkClearColorValue fillValue,const BufferValidator<T> & validator,const CmdBufferType cmdBufferType)114 CopyImageToBufferTestInstance<T>::CopyImageToBufferTestInstance	(Context&						ctx,
115 																 const vk::VkClearColorValue	fillValue,
116 																 const BufferValidator<T>&		validator,
117 																 const CmdBufferType			cmdBufferType)
118 	: ProtectedTestInstance	(ctx)
119 	, m_imageFormat			(vk::VK_FORMAT_R32G32B32A32_UINT)
120 	, m_fillValue			(fillValue)
121 	, m_validator			(validator)
122 	, m_cmdBufferType		(cmdBufferType)
123 {
124 }
125 
126 template<typename T>
iterate()127 tcu::TestStatus CopyImageToBufferTestInstance<T>::iterate()
128 {
129 	ProtectedContext&					ctx					(m_protectedContext);
130 	const vk::DeviceInterface&			vk					= ctx.getDeviceInterface();
131 	const vk::VkDevice					device				= ctx.getDevice();
132 	const vk::VkQueue					queue				= ctx.getQueue();
133 	const deUint32						queueFamilyIndex	= ctx.getQueueFamilyIndex();
134 
135 	// Create image
136 	de::MovePtr<vk::ImageWithMemory>	colorImage			= createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
137 																			RENDER_WIDTH, RENDER_HEIGHT,
138 																			m_imageFormat,
139 																			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT
140 																			| vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
141 	de::MovePtr<vk::BufferWithMemory>	dstBuffer			(makeBuffer(ctx,
142 																		PROTECTION_ENABLED,
143 																		queueFamilyIndex,
144 																		(deUint32)(BUFFER_SIZE * sizeof(deUint32)),
145 																		vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
146 																			| vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
147 																		vk::MemoryRequirement::Protected));
148 
149 	vk::Unique<vk::VkCommandPool>		cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
150 	vk::Unique<vk::VkCommandBuffer>		cmdBuffer			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
151 	vk::Unique<vk::VkCommandBuffer>		secondaryCmdBuffer	(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
152 	vk::VkCommandBuffer					targetCmdBuffer		= (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
153 
154 	// Begin cmd buffer
155 	beginCommandBuffer(vk, *cmdBuffer);
156 
157 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
158 	{
159 		// Begin secondary command buffer
160 		const vk::VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
161 		{
162 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
163 			DE_NULL,
164 			(vk::VkRenderPass)0u,										// renderPass
165 			0u,															// subpass
166 			(vk::VkFramebuffer)0u,										// framebuffer
167 			VK_FALSE,													// occlusionQueryEnable
168 			(vk::VkQueryControlFlags)0u,								// queryFlags
169 			(vk::VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
170 		};
171 		beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, secCmdBufInheritInfo);
172 	}
173 
174 	// Start image barrier for source image.
175 	{
176 		const vk::VkImageMemoryBarrier	startImgBarrier		=
177 		{
178 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
179 			DE_NULL,											// const void*			pNext
180 			0,													// VkAccessFlags		srcAccessMask
181 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		dstAccessMask
182 			vk::VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout		oldLayout
183 			vk::VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout		newLayout
184 			queueFamilyIndex,									// uint32_t				srcQueueFamilyIndex
185 			queueFamilyIndex,									// uint32_t				dstQueueFamilyIndex
186 			**colorImage,										// VkImage				image
187 			{
188 				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags	aspectMask
189 				0u,												// uint32_t				baseMipLevel
190 				1u,												// uint32_t				mipLevels
191 				0u,												// uint32_t				baseArraySlice
192 				1u,												// uint32_t				subresourceRange
193 			}
194 		};
195 
196 		vk.cmdPipelineBarrier(targetCmdBuffer,
197 							  vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
198 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
199 							  (vk::VkDependencyFlags)0,
200 							  0, (const vk::VkMemoryBarrier*)DE_NULL,
201 							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
202 							  1, &startImgBarrier);
203 	}
204 
205 	// Image clear
206 	const vk::VkImageSubresourceRange subresourceRange =
207 	{
208 		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
209 		0u,								// uint32_t				baseMipLevel
210 		1u,								// uint32_t				levelCount
211 		0u,								// uint32_t				baseArrayLayer
212 		1u,								// uint32_t				layerCount
213 	};
214 
215 	vk.cmdClearColorImage(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_GENERAL, &m_fillValue, 1, &subresourceRange);
216 
217 	// Image barrier to change accessMask to transfer read bit for source image.
218 	{
219 		const vk::VkImageMemoryBarrier initializeBarrier =
220 		{
221 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
222 			DE_NULL,											// const void*			pNext
223 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		srcAccessMask
224 			vk::VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags		dstAccessMask
225 			vk::VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout		oldLayout
226 			vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout		newLayout
227 			queueFamilyIndex,									// uint32_t				srcQueueFamilyIndex
228 			queueFamilyIndex,									// uint32_t				dstQueueFamilyIndex
229 			**colorImage,										// VkImage				image
230 			{
231 				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags	aspectMask
232 				0u,												// uint32_t				baseMipLevel
233 				1u,												// uint32_t				mipLevels
234 				0u,												// uint32_t				baseArraySlice
235 				1u,												// uint32_t				subresourceRange
236 			}
237 		};
238 
239 		vk.cmdPipelineBarrier(targetCmdBuffer,
240 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
241 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
242 							  (vk::VkDependencyFlags)0,
243 							  0, (const vk::VkMemoryBarrier*)DE_NULL,
244 							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
245 							  1, &initializeBarrier);
246 	}
247 
248 	// Copy image to buffer
249 	const vk::VkImageSubresourceLayers	subresourceLayers	=
250 	{
251 		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
252 		0u,								// uint32_t				mipLevel
253 		0u,								// uint32_t				baseArrayLayer
254 		1u,								// uint32_t				layerCount
255 	};
256 	const vk::VkOffset3D				nullOffset			= {0u, 0u, 0u};
257 	const vk::VkExtent3D				imageExtent			= {(deUint32)RENDER_WIDTH, (deUint32)RENDER_HEIGHT, 1u};
258 	const vk::VkBufferImageCopy			copyRegion			=
259 	{
260 		0ull,							// VkDeviceSize				srcOffset;
261 		0,								// uint32_t					bufferRowLength
262 		0,								// uint32_t					bufferImageHeight
263 		subresourceLayers,				// VkImageSubresourceLayers	imageSubresource
264 		nullOffset,						// VkOffset3D				imageOffset
265 		imageExtent,					// VkExtent3D				imageExtent
266 	};
267 	vk.cmdCopyImageToBuffer(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **dstBuffer, 1u, &copyRegion);
268 
269 	{
270 		// Buffer validator reads buffer in compute shader
271 		const vk::VkBufferMemoryBarrier	endBufferBarrier		=
272 		{
273 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType		sType
274 			DE_NULL,											// const void*			pNext
275 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		srcAccessMask
276 			vk::VK_ACCESS_SHADER_READ_BIT,						// VkAccessFlags		dstAccessMask
277 			queueFamilyIndex,									// uint32_t				srcQueueFamilyIndex
278 			queueFamilyIndex,									// uint32_t				dstQueueFamilyIndex
279 			**dstBuffer,										// VkBuffer				buffer
280 			0u,													// VkDeviceSize			offset
281 			VK_WHOLE_SIZE,										// VkDeviceSize			size
282 		};
283 		vk.cmdPipelineBarrier(targetCmdBuffer,
284 								vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
285 								vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
286 								(vk::VkDependencyFlags)0,
287 								0, (const vk::VkMemoryBarrier*)DE_NULL,
288 								1, &endBufferBarrier,
289 								0, (const vk::VkImageMemoryBarrier*)DE_NULL);
290 	}
291 
292 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
293 	{
294 		endCommandBuffer(vk, *secondaryCmdBuffer);
295 		vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
296 	}
297 
298 	endCommandBuffer(vk, *cmdBuffer);
299 
300 	// Submit command buffer
301 	const vk::Unique<vk::VkFence>	fence		(vk::createFence(vk, device));
302 	VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
303 
304 	// Log out test data
305 	ctx.getTestContext().getLog()
306 		<< tcu::TestLog::Message << "Fill value: " << m_fillValue << tcu::TestLog::EndMessage;
307 
308 	// Validate resulting buffer
309 	if (m_validator.validateBuffer(ctx, **dstBuffer))
310 		return tcu::TestStatus::pass("Everything went OK");
311 	else
312 		return tcu::TestStatus::fail("Something went really wrong");
313 }
314 
createCopyImageToFloatBufferTests(tcu::TestContext & testCtx,CmdBufferType cmdBufferType)315 tcu::TestCaseGroup*	createCopyImageToFloatBufferTests(tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
316 {
317 	struct {
318 		const vk::VkClearColorValue		fillValue;
319 		const ValidationDataVec4		data;
320 	} testData[] = {
321 		{	{ { 0.0f, 0.0f, 0.0f, 0.0f } },
322 			{
323 				{ tcu::IVec4(0),	tcu::IVec4(1),		tcu::IVec4(3),		tcu::IVec4(7)		},
324 				{ tcu::Vec4(0.0f),	tcu::Vec4(0.0f),	tcu::Vec4(0.0f),	tcu::Vec4(0.0f)		}
325 			}
326 		},
327 		{	{ { 1.0f, 1.0f, 1.0f, 1.0f } },
328 			{
329 				{ tcu::IVec4(2),	tcu::IVec4(4),		tcu::IVec4(16),		tcu::IVec4(15)		},
330 				{ tcu::Vec4(1.0f),	tcu::Vec4(1.0f),	tcu::Vec4(1.0f),	tcu::Vec4(1.0f)		}
331 			}
332 		},
333 		{	{ { 0.24f, 0.24f, 0.24f, 0.24f } },
334 			{
335 				{ tcu::IVec4(3),	tcu::IVec4(7),		tcu::IVec4(17),		tcu::IVec4(37)		},
336 				{ tcu::Vec4(0.24f),	tcu::Vec4(0.24f),	tcu::Vec4(0.24f),	tcu::Vec4(0.24f)	}
337 			}
338 		},
339 		{	{ { 0.68f, 0.68f, 0.68f, 0.68f } },
340 			{
341 				{ tcu::IVec4(7),	tcu::IVec4(11),		tcu::IVec4(21),		tcu::IVec4(40)		},
342 				{ tcu::Vec4(0.68f),	tcu::Vec4(0.68f),	tcu::Vec4(0.68f),	tcu::Vec4(0.68f)	}
343 			}
344 		},
345 		{	{ { 0.92f, 0.92f, 0.92f, 0.92f } },
346 			{
347 				{ tcu::IVec4(5),	tcu::IVec4(21),		tcu::IVec4(40),		tcu::IVec4(57)		},
348 				{ tcu::Vec4(0.92f),	tcu::Vec4(0.92f),	tcu::Vec4(0.92f),	tcu::Vec4(0.92f)	}
349 			}
350 		},
351 		{	{ { 0.49f, 0.49f, 0.49f, 0.49f } },
352 			{
353 				{ tcu::IVec4(23),	tcu::IVec4(37),		tcu::IVec4(51),		tcu::IVec4(63)		},
354 				{ tcu::Vec4(0.49f),	tcu::Vec4(0.49f),	tcu::Vec4(0.49f),	tcu::Vec4(0.49f)	}
355 			}
356 		},
357 	};
358 
359 	de::MovePtr<tcu::TestCaseGroup>	copyStaticTests		(new tcu::TestCaseGroup(testCtx, "static", "Copy Image to Buffer Tests with static input"));
360 
361 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
362 	{
363 		DE_ASSERT(testData[ndx].data.positions[0].x() < MAX_POSITION);
364 		DE_ASSERT(testData[ndx].data.positions[1].x() < MAX_POSITION);
365 		DE_ASSERT(testData[ndx].data.positions[2].x() < MAX_POSITION);
366 		DE_ASSERT(testData[ndx].data.positions[3].x() < MAX_POSITION);
367 
368 		const std::string name = "copy_" + de::toString(ndx + 1);
369 		copyStaticTests->addChild(new CopyImageToBufferTestCase<tcu::Vec4>(testCtx, name.c_str(), testData[ndx].fillValue, testData[ndx].data, cmdBufferType, vk::VK_FORMAT_R32G32B32A32_SFLOAT));
370 	}
371 
372 	/* Add a few randomized tests */
373 	de::MovePtr<tcu::TestCaseGroup>	copyRandomTests		(new tcu::TestCaseGroup(testCtx, "random", "Copy Image to Buffer Tests with random input"));
374 	const int						testCount			= 10;
375 	de::Random						rnd					(testCtx.getCommandLine().getBaseSeed());
376 	for (int ndx = 0; ndx < testCount; ++ndx)
377 	{
378 		const std::string	name		= "copy_" + de::toString(ndx + 1);
379 		vk::VkClearValue	clearValue	= vk::makeClearValueColorVec4(tcu::randomVec4(rnd));
380 		const tcu::Vec4		refValue	(clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]);
381 		const tcu::IVec4	vec0		= tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
382 		const tcu::IVec4	vec1		= tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
383 		const tcu::IVec4	vec2		= tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
384 		const tcu::IVec4	vec3		= tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
385 
386 		ValidationDataVec4	data		=
387 		{
388 			{ vec0, vec1, vec2, vec3 },
389 			{ refValue, refValue, refValue, refValue }
390 		};
391 
392 		DE_ASSERT(data.positions[0].x() < MAX_POSITION);
393 		DE_ASSERT(data.positions[1].x() < MAX_POSITION);
394 		DE_ASSERT(data.positions[2].x() < MAX_POSITION);
395 		DE_ASSERT(data.positions[3].x() < MAX_POSITION);
396 
397 		copyRandomTests->addChild(new CopyImageToBufferTestCase<tcu::Vec4>(testCtx, name.c_str(), clearValue.color, data, cmdBufferType, vk::VK_FORMAT_R32G32B32A32_SFLOAT));
398 	}
399 
400 	std::string groupName = getCmdBufferTypeStr(cmdBufferType);
401 	std::string groupDesc = "Copy Image to Buffer Tests with " + groupName + " command buffer";
402 	de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
403 	copyTests->addChild(copyStaticTests.release());
404 	copyTests->addChild(copyRandomTests.release());
405 	return copyTests.release();
406 }
407 
408 } // anonymous
409 
createCopyImageToFloatBufferTests(tcu::TestContext & testCtx)410 tcu::TestCaseGroup*	createCopyImageToFloatBufferTests (tcu::TestContext& testCtx)
411 {
412 	de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, "copy_image_to_float_buffer", "Copy Image to Buffer Tests"));
413 
414 	copyTests->addChild(createCopyImageToFloatBufferTests(testCtx, CMD_BUFFER_PRIMARY));
415 	copyTests->addChild(createCopyImageToFloatBufferTests(testCtx, CMD_BUFFER_SECONDARY));
416 
417 	return copyTests.release();
418 }
419 
420 } // ProtectedMem
421 } // vkt
422