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