• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
BufferValidator(const ValidationData<T> data)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 
BufferValidator(const ValidationDataStorage<T> data)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 
~BufferValidator()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<>
initPrograms(vk::SourceCollections & programCollection) const115 inline void BufferValidator<tcu::UVec4>::initPrograms (vk::SourceCollections& programCollection) const
116 {
117 	initBufferValidatorPrograms(programCollection, TYPE_UINT, m_bufferType);
118 }
119 
120 template<>
initPrograms(vk::SourceCollections & programCollection) const121 inline void BufferValidator<tcu::IVec4>::initPrograms (vk::SourceCollections& programCollection) const
122 {
123 	initBufferValidatorPrograms(programCollection, TYPE_INT, m_bufferType);
124 }
125 
126 template<>
initPrograms(vk::SourceCollections & programCollection) const127 inline void BufferValidator<tcu::Vec4>::initPrograms (vk::SourceCollections& programCollection) const
128 {
129 	initBufferValidatorPrograms(programCollection, TYPE_FLOAT, m_bufferType);
130 }
131 
132 template<typename T>
getReferenceDataSize() const133 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>
getReferenceDataSrc() const139 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>
printReferenceInfo(ProtectedContext & ctx) const145 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>
validateBuffer(ProtectedContext & ctx,const vk::VkBuffer buffer) const172 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