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