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