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