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