Home | History | Annotate | Download | only in protected_memory
      1 #ifndef _VKTPROTECTEDMEMBUFFERVALIDATOR_HPP
      2 #define _VKTPROTECTEDMEMBUFFERVALIDATOR_HPP
      3 /*------------------------------------------------------------------------
      4  * Vulkan Conformance Tests
      5  * ------------------------
      6  *
      7  * Copyright (c) 2017 The Khronos Group Inc.
      8  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
      9  *
     10  * Licensed under the Apache License, Version 2.0 (the "License");
     11  * you may not use this file except in compliance with the License.
     12  * You may obtain a copy of the License at
     13  *
     14  *      http://www.apache.org/licenses/LICENSE-2.0
     15  *
     16  * Unless required by applicable law or agreed to in writing, software
     17  * distributed under the License is distributed on an "AS IS" BASIS,
     18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     19  * See the License for the specific language governing permissions and
     20  * limitations under the License.
     21  *
     22  *//*!
     23  * \file
     24  * \brief Protected content buffer validator helper
     25  *//*--------------------------------------------------------------------*/
     26 
     27 #include "tcuVector.hpp"
     28 #include "vkDefs.hpp"
     29 #include "vktTestCase.hpp"
     30 #include "tcuVector.hpp"
     31 #include "tcuTestLog.hpp"
     32 
     33 #include "vkBuilderUtil.hpp"
     34 #include "vkPrograms.hpp"
     35 #include "vkTypeUtil.hpp"
     36 #include "vkCmdUtil.hpp"
     37 #include "vktTestCase.hpp"
     38 #include "vktTestGroupUtil.hpp"
     39 #include "tcuStringTemplate.hpp"
     40 
     41 #include "vktProtectedMemUtils.hpp"
     42 #include "vktProtectedMemContext.hpp"
     43 
     44 namespace vkt
     45 {
     46 namespace ProtectedMem
     47 {
     48 
     49 class ProtectedContext;
     50 
     51 template<typename T>
     52 struct ValidationData {
     53 	const tcu::IVec4	positions[4];
     54 	const T				values[4];
     55 };
     56 
     57 template<typename T>
     58 struct ValidationDataStorage {
     59 	T					values;
     60 };
     61 
     62 typedef ValidationData<tcu::UVec4>	ValidationDataUVec4;
     63 typedef ValidationData<tcu::IVec4>	ValidationDataIVec4;
     64 typedef ValidationData<tcu::Vec4>	ValidationDataVec4;
     65 
     66 enum TestType {
     67 	TYPE_UINT,
     68 	TYPE_INT,
     69 	TYPE_FLOAT,
     70 };
     71 
     72 enum BufferType {
     73 	SAMPLER_BUFFER,
     74 	STORAGE_BUFFER,
     75 };
     76 
     77 void					initBufferValidatorPrograms		(vk::SourceCollections&	programCollection, TestType testType, BufferType bufferType);
     78 vk::VkDescriptorType	getDescriptorType				(BufferType bufferType);
     79 
     80 template<typename T>
     81 class BufferValidator
     82 {
     83 public:
     84 									BufferValidator			(const ValidationData<T> data)
     85 										: m_refData			(data)
     86 										, m_refDataStorage	(*reinterpret_cast<ValidationDataStorage<T>*>( &std::vector<char>(sizeof(ValidationDataStorage<T>), '\0').front()))
     87 										, m_bufferType		(SAMPLER_BUFFER)
     88 									{
     89 									}
     90 
     91 									BufferValidator			(const ValidationDataStorage<T> data)
     92 										: m_refData			(*reinterpret_cast<ValidationData<T>*>( &std::vector<char>(sizeof(ValidationData<T>), '\0').front()))
     93 										, m_refDataStorage	(data)
     94 										, m_bufferType		(STORAGE_BUFFER)
     95 									{
     96 									}
     97 
     98 									~BufferValidator		() {}
     99 	void							initPrograms			(vk::SourceCollections&	programCollection) const;
    100 
    101 	bool							validateBuffer			(ProtectedContext&	ctx,
    102 																 const vk::VkBuffer	buffer) const;
    103 private:
    104 	deUint32						getReferenceDataSize	() const;
    105 	const void *					getReferenceDataSrc		() const;
    106 	void							printReferenceInfo		(ProtectedContext&		ctx) const;
    107 
    108 	const ValidationData<T>			m_refData;
    109 	const ValidationDataStorage<T>	m_refDataStorage;
    110 
    111 	BufferType						m_bufferType;
    112 };
    113 
    114 template<>
    115 inline void BufferValidator<tcu::UVec4>::initPrograms (vk::SourceCollections& programCollection) const
    116 {
    117 	initBufferValidatorPrograms(programCollection, TYPE_UINT, m_bufferType);
    118 }
    119 
    120 template<>
    121 inline void BufferValidator<tcu::IVec4>::initPrograms (vk::SourceCollections& programCollection) const
    122 {
    123 	initBufferValidatorPrograms(programCollection, TYPE_INT, m_bufferType);
    124 }
    125 
    126 template<>
    127 inline void BufferValidator<tcu::Vec4>::initPrograms (vk::SourceCollections& programCollection) const
    128 {
    129 	initBufferValidatorPrograms(programCollection, TYPE_FLOAT, m_bufferType);
    130 }
    131 
    132 template<typename T>
    133 deUint32 BufferValidator<T>::getReferenceDataSize () const
    134 {
    135 	return m_bufferType == SAMPLER_BUFFER ? (deUint32)sizeof(m_refData) : (deUint32)sizeof(m_refDataStorage);
    136 }
    137 
    138 template<typename T>
    139 const void * BufferValidator<T>::getReferenceDataSrc () const
    140 {
    141 	return m_bufferType == SAMPLER_BUFFER ? (void*)&m_refData : (void*)&m_refDataStorage;
    142 }
    143 
    144 template<typename T>
    145 void BufferValidator<T>::printReferenceInfo (ProtectedContext& ctx) const
    146 {
    147 	if (m_bufferType == SAMPLER_BUFFER)
    148 	{
    149 		ctx.getTestContext().getLog()
    150 				<< tcu::TestLog::Message << "Reference positions: \n"
    151 				<< "1: " << m_refData.positions[0] << "\n"
    152 				<< "2: " << m_refData.positions[1] << "\n"
    153 				<< "3: " << m_refData.positions[2] << "\n"
    154 				<< "4: " << m_refData.positions[3] << "\n"
    155 				<< tcu::TestLog::EndMessage
    156 				<< tcu::TestLog::Message << "Reference fill values: \n"
    157 				<< "1: " << m_refData.values[0] << "\n"
    158 				<< "2: " << m_refData.values[1] << "\n"
    159 				<< "3: " << m_refData.values[2] << "\n"
    160 				<< "4: " << m_refData.values[3] << "\n"
    161 				<< tcu::TestLog::EndMessage;
    162 	} else if (m_bufferType == STORAGE_BUFFER)
    163 	{
    164 		ctx.getTestContext().getLog()
    165 				<< tcu::TestLog::Message << "Reference values: \n"
    166 				<< "1: " << m_refDataStorage.values << "\n"
    167 				<< tcu::TestLog::EndMessage;
    168 	}
    169 }
    170 
    171 template<typename T>
    172 bool BufferValidator<T>::validateBuffer (ProtectedContext&		ctx,
    173 										 const vk::VkBuffer		buffer) const
    174 {
    175 	// Log out a few reference info
    176 	printReferenceInfo(ctx);
    177 
    178 	const deUint64							oneSec				= 1000 * 1000 * 1000;
    179 
    180 	const vk::DeviceInterface&				vk					= ctx.getDeviceInterface();
    181 	const vk::VkDevice						device				= ctx.getDevice();
    182 	const vk::VkQueue						queue				= ctx.getQueue();
    183 	const deUint32							queueFamilyIndex	= ctx.getQueueFamilyIndex();
    184 
    185 	vk::Move<vk::VkBufferView>				bufferView;
    186 
    187 	const deUint32							refDataSize			= getReferenceDataSize();
    188 	de::UniquePtr<vk::BufferWithMemory>		refUniform			(makeBuffer(ctx,
    189 																 PROTECTION_DISABLED,
    190 																 queueFamilyIndex,
    191 																 refDataSize,
    192 																 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
    193 																 vk::MemoryRequirement::HostVisible));
    194 
    195 	// Set the reference uniform data
    196 	{
    197 		deMemcpy(refUniform->getAllocation().getHostPtr(), getReferenceDataSrc(), refDataSize);
    198 		vk::flushMappedMemoryRange(vk, device, refUniform->getAllocation().getMemory(), refUniform->getAllocation().getOffset(), refDataSize);
    199 	}
    200 
    201 	const deUint32							helperBufferSize	= (deUint32)(2 * sizeof(deUint32));
    202 	de::MovePtr<vk::BufferWithMemory>		helperBuffer		(makeBuffer(ctx,
    203 																 PROTECTION_ENABLED,
    204 																 queueFamilyIndex,
    205 																 helperBufferSize,
    206 																 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
    207 																 vk::MemoryRequirement::Protected));
    208 	vk::Unique<vk::VkShaderModule>			resetSSBOShader		(vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("ResetSSBO"), 0));
    209 	vk::Unique<vk::VkShaderModule>			validatorShader		(vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("BufferValidator"), 0));
    210 
    211 	// Create descriptors
    212 	vk::Unique<vk::VkDescriptorSetLayout>	descriptorSetLayout	(vk::DescriptorSetLayoutBuilder()
    213 																	.addSingleBinding(getDescriptorType(m_bufferType), vk::VK_SHADER_STAGE_COMPUTE_BIT)
    214 																	.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
    215 																	.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
    216 																	.build(vk, device));
    217 	vk::Unique<vk::VkDescriptorPool>		descriptorPool		(vk::DescriptorPoolBuilder()
    218 																	.addType(getDescriptorType(m_bufferType), 1u)
    219 																	.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
    220 																	.addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
    221 																	.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
    222 	vk::Unique<vk::VkDescriptorSet>			descriptorSet		(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
    223 
    224 
    225 	// Update descriptor set information
    226 	{
    227 		vk::VkDescriptorBufferInfo	descRefUniform	= makeDescriptorBufferInfo(**refUniform, 0, refDataSize);
    228 		vk::VkDescriptorBufferInfo	descBuffer		= makeDescriptorBufferInfo(**helperBuffer, 0, helperBufferSize);
    229 
    230 		vk::DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
    231 		switch (m_bufferType)
    232 		{
    233 			case SAMPLER_BUFFER:
    234 			{
    235 				const vk::VkBufferViewCreateInfo		viewParams			=
    236 					{
    237 						vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,	// VkStructureType			sType
    238 						DE_NULL,										// const void*				pNext
    239 						0u,												// VkBufferViewCreateFlags	flags
    240 						buffer,											// VkBuffer					buffer
    241 						vk::VK_FORMAT_R32G32B32A32_UINT,				// VkFormat					format
    242 						0u,												// VkDeviceSize				offset
    243 						VK_WHOLE_SIZE									// VkDeviceSize				range
    244 					};
    245 				bufferView = vk::Move<vk::VkBufferView> (vk::createBufferView(vk, device, &viewParams));
    246 				descriptorSetUpdateBuilder
    247 					.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, &bufferView.get());
    248 				break;
    249 			}
    250 			case STORAGE_BUFFER:
    251 			{
    252 				const deUint32					testBufferSize	= (deUint32)(sizeof(ValidationDataStorage<T>));
    253 				vk::VkDescriptorBufferInfo		descTestBuffer	= makeDescriptorBufferInfo(buffer, 0, testBufferSize);
    254 				descriptorSetUpdateBuilder
    255 					.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descTestBuffer);
    256 				break;
    257 			}
    258 		}
    259 		descriptorSetUpdateBuilder
    260 			.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descBuffer)
    261 			.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descRefUniform)
    262 		.update(vk, device);
    263 	}
    264 
    265 	// Build pipeline
    266 	vk::Unique<vk::VkPipelineLayout>		pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));
    267 
    268 	vk::Unique<vk::VkCommandPool>			cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
    269 
    270 	// Reset helper SSBO
    271 	{
    272 		const vk::Unique<vk::VkFence>		fence				(vk::createFence(vk, device));
    273 		vk::Unique<vk::VkPipeline>			resetSSBOPipeline	(makeComputePipeline(vk, device, *pipelineLayout, *resetSSBOShader, DE_NULL));
    274 		vk::Unique<vk::VkCommandBuffer>		resetCmdBuffer		(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
    275 		beginCommandBuffer(vk, *resetCmdBuffer);
    276 
    277 		vk.cmdBindPipeline(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *resetSSBOPipeline);
    278 		vk.cmdBindDescriptorSets(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
    279 		vk.cmdDispatch(*resetCmdBuffer, 1u, 1u, 1u);
    280 
    281 		endCommandBuffer(vk, *resetCmdBuffer);
    282 		VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *resetCmdBuffer, *fence, ~0ull));
    283 	}
    284 
    285 	// Create validation compute commands & submit
    286 	vk::VkResult							queueSubmitResult;
    287 	{
    288 		const vk::Unique<vk::VkFence>		fence				(vk::createFence(vk, device));
    289 		vk::Unique<vk::VkPipeline>			validationPipeline	(makeComputePipeline(vk, device, *pipelineLayout, *validatorShader, DE_NULL));
    290 		vk::Unique<vk::VkCommandBuffer>		cmdBuffer			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
    291 
    292 		beginCommandBuffer(vk, *cmdBuffer);
    293 
    294 		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *validationPipeline);
    295 		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
    296 		vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
    297 
    298 		endCommandBuffer(vk, *cmdBuffer);
    299 
    300 		queueSubmitResult = queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, oneSec);
    301 	}
    302 
    303 	// \todo do we need to check the fence status?
    304 	if (queueSubmitResult == vk::VK_TIMEOUT)
    305 		return false;
    306 
    307 	// at this point the submit result should be VK_TRUE
    308 	VK_CHECK(queueSubmitResult);
    309 	return true;
    310 }
    311 
    312 
    313 } // ProtectedMem
    314 } // vkt
    315 
    316 #endif // _VKTPROTECTEDMEMBUFFERVALIDATOR_HPP
    317