1 #ifndef _VKTPROTECTEDMEMBUFFERVALIDATOR_HPP
2 #define _VKTPROTECTEDMEMBUFFERVALIDATOR_HPP
3 /*------------------------------------------------------------------------
4 * Vulkan Conformance Tests
5 * ------------------------
6 *
7 * Copyright (c) 2017 The Khronos Group Inc.
8 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Protected content buffer validator helper
25 *//*--------------------------------------------------------------------*/
26
27 #include "tcuVector.hpp"
28 #include "vkDefs.hpp"
29 #include "vktTestCase.hpp"
30 #include "tcuVector.hpp"
31 #include "tcuTestLog.hpp"
32
33 #include "vkBuilderUtil.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 #include "vktTestCase.hpp"
39 #include "vktTestGroupUtil.hpp"
40 #include "tcuStringTemplate.hpp"
41
42 #include "vktProtectedMemUtils.hpp"
43 #include "vktProtectedMemContext.hpp"
44
45 namespace vkt
46 {
47 namespace ProtectedMem
48 {
49
50 class ProtectedContext;
51
52 template<typename T>
53 struct ValidationData {
54 const tcu::IVec4 positions[4];
55 const T values[4];
56 };
57
58 template<typename T>
59 struct ValidationDataStorage {
60 T values;
61 };
62
63 typedef ValidationData<tcu::UVec4> ValidationDataUVec4;
64 typedef ValidationData<tcu::IVec4> ValidationDataIVec4;
65 typedef ValidationData<tcu::Vec4> ValidationDataVec4;
66
67 enum TestType {
68 TYPE_UINT,
69 TYPE_INT,
70 TYPE_FLOAT,
71 };
72
73 enum BufferType {
74 SAMPLER_BUFFER,
75 STORAGE_BUFFER,
76 };
77
78 void initBufferValidatorPrograms (vk::SourceCollections& programCollection, TestType testType, BufferType bufferType);
79 vk::VkDescriptorType getDescriptorType (BufferType bufferType);
80
81 template<typename T>
82 class BufferValidator
83 {
84 public:
BufferValidator(const ValidationData<T> data,vk::VkFormat format)85 BufferValidator (const ValidationData<T> data, vk::VkFormat format)
86 : m_refData (data)
87 , m_refDataStorage (*reinterpret_cast<ValidationDataStorage<T>*>( &std::vector<char>(sizeof(ValidationDataStorage<T>), '\0').front()))
88 , m_bufferType (SAMPLER_BUFFER)
89 , m_format (format)
90 {
91 }
92
BufferValidator(const ValidationDataStorage<T> data,vk::VkFormat format)93 BufferValidator (const ValidationDataStorage<T> data, vk::VkFormat format)
94 : m_refData (*reinterpret_cast<ValidationData<T>*>( &std::vector<char>(sizeof(ValidationData<T>), '\0').front()))
95 , m_refDataStorage (data)
96 , m_bufferType (STORAGE_BUFFER)
97 , m_format (format)
98 {
99 }
100
~BufferValidator()101 ~BufferValidator () {}
102 void initPrograms (vk::SourceCollections& programCollection) const;
103
104 bool validateBuffer (ProtectedContext& ctx,
105 const vk::VkBuffer buffer) const;
106 private:
107 deUint32 getReferenceDataSize () const;
108 const void * getReferenceDataSrc () const;
109 void printReferenceInfo (ProtectedContext& ctx) const;
110
111 const ValidationData<T> m_refData;
112 const ValidationDataStorage<T> m_refDataStorage;
113
114 BufferType m_bufferType;
115 vk::VkFormat m_format;
116 };
117
118 template<>
initPrograms(vk::SourceCollections & programCollection) const119 inline void BufferValidator<tcu::UVec4>::initPrograms (vk::SourceCollections& programCollection) const
120 {
121 initBufferValidatorPrograms(programCollection, TYPE_UINT, m_bufferType);
122 }
123
124 template<>
initPrograms(vk::SourceCollections & programCollection) const125 inline void BufferValidator<tcu::IVec4>::initPrograms (vk::SourceCollections& programCollection) const
126 {
127 initBufferValidatorPrograms(programCollection, TYPE_INT, m_bufferType);
128 }
129
130 template<>
initPrograms(vk::SourceCollections & programCollection) const131 inline void BufferValidator<tcu::Vec4>::initPrograms (vk::SourceCollections& programCollection) const
132 {
133 initBufferValidatorPrograms(programCollection, TYPE_FLOAT, m_bufferType);
134 }
135
136 template<typename T>
getReferenceDataSize() const137 deUint32 BufferValidator<T>::getReferenceDataSize () const
138 {
139 return m_bufferType == SAMPLER_BUFFER ? (deUint32)sizeof(m_refData) : (deUint32)sizeof(m_refDataStorage);
140 }
141
142 template<typename T>
getReferenceDataSrc() const143 const void * BufferValidator<T>::getReferenceDataSrc () const
144 {
145 return m_bufferType == SAMPLER_BUFFER ? (void*)&m_refData : (void*)&m_refDataStorage;
146 }
147
148 template<typename T>
printReferenceInfo(ProtectedContext & ctx) const149 void BufferValidator<T>::printReferenceInfo (ProtectedContext& ctx) const
150 {
151 if (m_bufferType == SAMPLER_BUFFER)
152 {
153 ctx.getTestContext().getLog()
154 << tcu::TestLog::Message << "Reference positions: \n"
155 << "1: " << m_refData.positions[0] << "\n"
156 << "2: " << m_refData.positions[1] << "\n"
157 << "3: " << m_refData.positions[2] << "\n"
158 << "4: " << m_refData.positions[3] << "\n"
159 << tcu::TestLog::EndMessage
160 << tcu::TestLog::Message << "Reference fill values: \n"
161 << "1: " << m_refData.values[0] << "\n"
162 << "2: " << m_refData.values[1] << "\n"
163 << "3: " << m_refData.values[2] << "\n"
164 << "4: " << m_refData.values[3] << "\n"
165 << tcu::TestLog::EndMessage;
166 } else if (m_bufferType == STORAGE_BUFFER)
167 {
168 ctx.getTestContext().getLog()
169 << tcu::TestLog::Message << "Reference values: \n"
170 << "1: " << m_refDataStorage.values << "\n"
171 << tcu::TestLog::EndMessage;
172 }
173 }
174
175 template<typename T>
validateBuffer(ProtectedContext & ctx,const vk::VkBuffer buffer) const176 bool BufferValidator<T>::validateBuffer (ProtectedContext& ctx,
177 const vk::VkBuffer buffer) const
178 {
179 // Log out a few reference info
180 printReferenceInfo(ctx);
181
182 const deUint64 oneSec = 1000 * 1000 * 1000;
183
184 const vk::DeviceInterface& vk = ctx.getDeviceInterface();
185 const vk::VkDevice device = ctx.getDevice();
186 const vk::VkQueue queue = ctx.getQueue();
187 const deUint32 queueFamilyIndex = ctx.getQueueFamilyIndex();
188
189 vk::Move<vk::VkBufferView> bufferView;
190
191 const deUint32 refDataSize = getReferenceDataSize();
192 de::UniquePtr<vk::BufferWithMemory> refUniform (makeBuffer(ctx,
193 PROTECTION_DISABLED,
194 queueFamilyIndex,
195 refDataSize,
196 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
197 vk::MemoryRequirement::HostVisible));
198
199 // Set the reference uniform data
200 {
201 deMemcpy(refUniform->getAllocation().getHostPtr(), getReferenceDataSrc(), refDataSize);
202 flushAlloc(vk, device, refUniform->getAllocation());
203 }
204
205 const deUint32 helperBufferSize = (deUint32)(2 * sizeof(deUint32));
206 de::MovePtr<vk::BufferWithMemory> helperBuffer (makeBuffer(ctx,
207 PROTECTION_ENABLED,
208 queueFamilyIndex,
209 helperBufferSize,
210 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
211 vk::MemoryRequirement::Protected));
212 vk::Unique<vk::VkShaderModule> resetSSBOShader (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("ResetSSBO"), 0));
213 vk::Unique<vk::VkShaderModule> validatorShader (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("BufferValidator"), 0));
214
215 // Create descriptors
216 vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (vk::DescriptorSetLayoutBuilder()
217 .addSingleBinding(getDescriptorType(m_bufferType), vk::VK_SHADER_STAGE_COMPUTE_BIT)
218 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
219 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
220 .build(vk, device));
221 vk::Unique<vk::VkDescriptorPool> descriptorPool (vk::DescriptorPoolBuilder()
222 .addType(getDescriptorType(m_bufferType), 1u)
223 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
224 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
225 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
226 vk::Unique<vk::VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
227
228
229 // Update descriptor set information
230 {
231 vk::VkDescriptorBufferInfo descRefUniform = makeDescriptorBufferInfo(**refUniform, 0, refDataSize);
232 vk::VkDescriptorBufferInfo descBuffer = makeDescriptorBufferInfo(**helperBuffer, 0, helperBufferSize);
233
234 vk::DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
235 switch (m_bufferType)
236 {
237 case SAMPLER_BUFFER:
238 {
239 const vk::VkBufferViewCreateInfo viewParams =
240 {
241 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType
242 DE_NULL, // const void* pNext
243 0u, // VkBufferViewCreateFlags flags
244 buffer, // VkBuffer buffer
245 m_format, // VkFormat format
246 0u, // VkDeviceSize offset
247 VK_WHOLE_SIZE // VkDeviceSize range
248 };
249 bufferView = vk::Move<vk::VkBufferView> (vk::createBufferView(vk, device, &viewParams));
250 descriptorSetUpdateBuilder
251 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, &bufferView.get());
252 break;
253 }
254 case STORAGE_BUFFER:
255 {
256 const deUint32 testBufferSize = (deUint32)(sizeof(ValidationDataStorage<T>));
257 vk::VkDescriptorBufferInfo descTestBuffer = makeDescriptorBufferInfo(buffer, 0, testBufferSize);
258 descriptorSetUpdateBuilder
259 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descTestBuffer);
260 break;
261 }
262 }
263 descriptorSetUpdateBuilder
264 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descBuffer)
265 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descRefUniform)
266 .update(vk, device);
267 }
268
269 // Build pipeline
270 vk::Unique<vk::VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
271
272 vk::Unique<vk::VkCommandPool> cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
273
274 // Reset helper SSBO
275 {
276 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
277 vk::Unique<vk::VkPipeline> resetSSBOPipeline (makeComputePipeline(vk, device, *pipelineLayout, *resetSSBOShader, DE_NULL));
278 vk::Unique<vk::VkCommandBuffer> resetCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
279 beginCommandBuffer(vk, *resetCmdBuffer);
280
281 vk.cmdBindPipeline(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *resetSSBOPipeline);
282 vk.cmdBindDescriptorSets(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
283 vk.cmdDispatch(*resetCmdBuffer, 1u, 1u, 1u);
284
285 endCommandBuffer(vk, *resetCmdBuffer);
286 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *resetCmdBuffer, *fence, ~0ull));
287 }
288
289 // Create validation compute commands & submit
290 vk::VkResult queueSubmitResult;
291 {
292 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
293 vk::Unique<vk::VkPipeline> validationPipeline (makeComputePipeline(vk, device, *pipelineLayout, *validatorShader, DE_NULL));
294 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
295
296 beginCommandBuffer(vk, *cmdBuffer);
297
298 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *validationPipeline);
299 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
300 vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
301
302 endCommandBuffer(vk, *cmdBuffer);
303
304 queueSubmitResult = queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, oneSec);
305 }
306
307 // \todo do we need to check the fence status?
308 if (queueSubmitResult == vk::VK_TIMEOUT)
309 return false;
310
311 // at this point the submit result should be VK_TRUE
312 VK_CHECK(queueSubmitResult);
313 return true;
314 }
315
316
317 } // ProtectedMem
318 } // vkt
319
320 #endif // _VKTPROTECTEDMEMBUFFERVALIDATOR_HPP
321