• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 image validator helper
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktProtectedMemImageValidator.hpp"
26 
27 #include "tcuTestLog.hpp"
28 #include "tcuStringTemplate.hpp"
29 
30 #include "vkBuilderUtil.hpp"
31 #include "vkPrograms.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vktTestCase.hpp"
35 #include "vktTestGroupUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 
39 #include "vktProtectedMemUtils.hpp"
40 #include "vktProtectedMemContext.hpp"
41 
42 namespace vkt
43 {
44 namespace ProtectedMem
45 {
46 
initPrograms(vk::SourceCollections & programCollection) const47 void ImageValidator::initPrograms (vk::SourceCollections& programCollection) const
48 {
49 	// Layout:
50 	//  set = 0, location = 0 -> uniform *sampler2D u_protectedImage
51 	//  set = 0, location = 1 -> buffer ProtectedHelper (2 * uint)
52 	//  set = 0, location = 2 -> uniform Data (2 * vec2 + 4 * vec4)
53 	const char* validatorShader = "#version 450\n"
54 					  "layout(local_size_x = 1) in;\n"
55 					  "\n"
56 					  "layout(set=0, binding=0) uniform ${SAMPLER_TYPE} u_protectedImage;\n"
57 					  "\n"
58 					  "layout(set=0, binding=1) buffer ProtectedHelper\n"
59 					  "{\n"
60 					  "    highp uint zero; // set to 0\n"
61 					  "    highp uint dummyOut;\n"
62 					  "} helper;\n"
63 					  "\n"
64 					  "layout(set=0, binding=2) uniform Data\n"
65 					  "{\n"
66 					  "    highp vec2 protectedImageCoord[4];\n"
67 					  "    highp vec4 protectedImageRef[4];\n"
68 					  "};\n"
69 					  "\n"
70 					  "void error ()\n"
71 					  "{\n"
72 					  "    for (uint x = 0; x < 10; x += helper.zero)\n"
73 					  "        atomicAdd(helper.dummyOut, 1u);\n"
74 					  "}\n"
75 					  "\n"
76 					  "bool compare (vec4 a, vec4 b, float threshold)\n"
77 					  "{\n"
78 					  "    return all(lessThanEqual(abs(a - b), vec4(threshold)));\n"
79 					  "}\n"
80 					  "\n"
81 					  "void main (void)\n"
82 					  "{\n"
83 					  "    float threshold = 0.1;\n"
84 					  "    for (uint i = 0; i < 4; i++)\n"
85 					  "    {\n"
86 					  "        if (!compare(texture(u_protectedImage, protectedImageCoord[i]), protectedImageRef[i], threshold))\n"
87 					  "            error();\n"
88 					  "    }\n"
89 					  "}\n";
90 
91 	const char* resetSSBOShader = "#version 450\n"
92 					  "layout(local_size_x = 1) in;\n"
93 					  "\n"
94 					  "layout(set=0, binding=1) buffer ProtectedHelper\n"
95 					  "{\n"
96 					  "    highp uint zero; // set to 0\n"
97 					  "    highp uint dummyOut;\n"
98 					  "} helper;\n"
99 					  "\n"
100 					  "void main (void)\n"
101 					  "{\n"
102 					  "    helper.zero = 0;\n"
103 					  "}\n";
104 
105 	programCollection.glslSources.add("ResetSSBO") << glu::ComputeSource(resetSSBOShader);
106 
107 	std::map<std::string, std::string> validationParams;
108 	validationParams["SAMPLER_TYPE"] = isIntFormat(m_imageFormat)	? "isampler2D" :
109 									   isUintFormat(m_imageFormat)	? "usampler2D" : "sampler2D";
110 
111 	programCollection.glslSources.add("ImageValidator") << glu::ComputeSource(tcu::StringTemplate(validatorShader).specialize(validationParams));
112 }
113 
validateImage(ProtectedContext & ctx,const ValidationData & refData,const vk::VkImage image,const vk::VkFormat imageFormat,const vk::VkImageLayout imageLayout) const114 bool ImageValidator::validateImage (ProtectedContext& ctx, const ValidationData& refData,
115 									const vk::VkImage image, const vk::VkFormat imageFormat, const vk::VkImageLayout imageLayout) const
116 {
117 	// Log out a few reference info
118 	{
119 		ctx.getTestContext().getLog()
120 			<< tcu::TestLog::Message << "Reference coordinates: \n"
121 				<< "1: " << refData.coords[0] << "\n"
122 				<< "2: " << refData.coords[1] << "\n"
123 				<< "3: " << refData.coords[2] << "\n"
124 				<< "4: " << refData.coords[3] << "\n"
125 				<< tcu::TestLog::EndMessage
126 			<< tcu::TestLog::Message << "Reference color values: \n"
127 				<< "1: " << refData.values[0] << "\n"
128 				<< "2: " << refData.values[1] << "\n"
129 				<< "3: " << refData.values[2] << "\n"
130 				<< "4: " << refData.values[3] << "\n"
131 			<< tcu::TestLog::EndMessage;
132 	}
133 
134 	const deUint64							oneSec				= 1000 * 1000 * 1000;
135 
136 	const vk::DeviceInterface&				vk					= ctx.getDeviceInterface();
137 	const vk::VkDevice						device				= ctx.getDevice();
138 	const vk::VkQueue						queue				= ctx.getQueue();
139 	const deUint32							queueFamilyIndex	= ctx.getQueueFamilyIndex();
140 
141 	const deUint32							refUniformSize		= sizeof(refData);
142 	de::UniquePtr<vk::BufferWithMemory>		refUniform			(makeBuffer(ctx,
143 																		PROTECTION_DISABLED,
144 																		queueFamilyIndex,
145 																		refUniformSize,
146 																		vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
147 																		vk::MemoryRequirement::HostVisible));
148 	// Set the reference uniform data
149 	{
150 		deMemcpy(refUniform->getAllocation().getHostPtr(), &refData, refUniformSize);
151 		flushAlloc(vk, device, refUniform->getAllocation());
152 	}
153 
154 	const deUint32							helperBufferSize	= (deUint32)(2 * sizeof(deUint32));
155 	de::MovePtr<vk::BufferWithMemory>		helperBuffer		(makeBuffer(ctx,
156 																			PROTECTION_ENABLED,
157 																			queueFamilyIndex,
158 																			helperBufferSize,
159 																			vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
160 																			vk::MemoryRequirement::Protected));
161 	vk::Unique<vk::VkShaderModule>			resetSSBOShader		(vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("ResetSSBO"), 0));
162 	vk::Unique<vk::VkShaderModule>			validatorShader		(vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("ImageValidator"), 0));
163 
164 	vk::Unique<vk::VkSampler>				sampler				(makeSampler(vk, device));
165 	const vk::VkImageViewCreateInfo			viewParams			=
166 	{
167 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// sType
168 		DE_NULL,										// pNext
169 		0u,												// flags
170 		image,											// image
171 		vk::VK_IMAGE_VIEW_TYPE_2D,						// viewType
172 		imageFormat,									// format
173 		vk::makeComponentMappingRGBA(),					// components
174 		{
175 			vk::VK_IMAGE_ASPECT_COLOR_BIT,	// aspectMask
176 			0u,								// baseMipLevel
177 			1u,								// mipLeves
178 			0u,								// baseArraySlice
179 			1u,								// arraySize
180 		}												// subresourceRange
181 	};
182 	vk::Unique<vk::VkImageView>				imageView			(vk::createImageView(vk, device, &viewParams));
183 
184 	// Create descriptors
185 	vk::Unique<vk::VkDescriptorSetLayout>	descriptorSetLayout(vk::DescriptorSetLayoutBuilder()
186 		.addSingleSamplerBinding(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_COMPUTE_BIT, DE_NULL)
187 		.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
188 		.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
189 		.build(vk, device));
190 	vk::Unique<vk::VkDescriptorPool>		descriptorPool(vk::DescriptorPoolBuilder()
191 		.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u)
192 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
193 		.addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
194 		.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
195 	vk::Unique<vk::VkDescriptorSet>			descriptorSet		(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
196 
197 	// Update descriptor set infirmation
198 	{
199 		vk::VkDescriptorBufferInfo	descRefUniform	= makeDescriptorBufferInfo(**refUniform, 0, refUniformSize);
200 		vk::VkDescriptorBufferInfo	descBuffer		= makeDescriptorBufferInfo(**helperBuffer, 0, helperBufferSize);
201 		vk::VkDescriptorImageInfo	descSampledImg	= makeDescriptorImageInfo(*sampler, *imageView, imageLayout);
202 
203 		vk::DescriptorSetUpdateBuilder()
204 			.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descSampledImg)
205 			.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descBuffer)
206 			.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descRefUniform)
207 			.update(vk, device);
208 	}
209 
210 	// Build pipeline
211 	vk::Unique<vk::VkPipelineLayout>		pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));
212 
213 	vk::Unique<vk::VkCommandPool>			cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
214 
215 	// Reset helper SSBO
216 	{
217 		const vk::Unique<vk::VkFence>		fence				(vk::createFence(vk, device));
218 		vk::Unique<vk::VkPipeline>			resetSSBOPipeline	(makeComputePipeline(vk, device, *pipelineLayout, *resetSSBOShader, DE_NULL));
219 		vk::Unique<vk::VkCommandBuffer>		resetCmdBuffer		(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
220 		beginCommandBuffer(vk, *resetCmdBuffer);
221 
222 		vk.cmdBindPipeline(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *resetSSBOPipeline);
223 		vk.cmdBindDescriptorSets(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
224 		vk.cmdDispatch(*resetCmdBuffer, 1u, 1u, 1u);
225 
226 		endCommandBuffer(vk, *resetCmdBuffer);
227 		VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *resetCmdBuffer, *fence, ~0ull));
228 	}
229 
230 	// Create validation compute commands & submit
231 	vk::VkResult							queueSubmitResult;
232 	{
233 		const vk::Unique<vk::VkFence>		fence				(vk::createFence(vk, device));
234 		vk::Unique<vk::VkPipeline>			validationPipeline	(makeComputePipeline(vk, device, *pipelineLayout, *validatorShader, DE_NULL));
235 		vk::Unique<vk::VkCommandBuffer>		cmdBuffer			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
236 
237 		beginCommandBuffer(vk, *cmdBuffer);
238 
239 		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *validationPipeline);
240 		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
241 		vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
242 
243 		endCommandBuffer(vk, *cmdBuffer);
244 
245 		queueSubmitResult										= queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, oneSec);
246 	}
247 
248 	// \todo do we need to check the fence status?
249 	if (queueSubmitResult == vk::VK_TIMEOUT)
250 		return false;
251 
252 	// at this point the submit result should be VK_TRUE
253 	VK_CHECK(queueSubmitResult);
254 	return true;
255 }
256 
257 } // ProtectedMem
258 } // vkt
259