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