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