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