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