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 "vktTestCase.hpp"
38 #include "vktTestGroupUtil.hpp"
39 #include "tcuStringTemplate.hpp"
40
41 #include "vktProtectedMemUtils.hpp"
42 #include "vktProtectedMemContext.hpp"
43
44 namespace vkt
45 {
46 namespace ProtectedMem
47 {
48
49 class ProtectedContext;
50
51 template<typename T>
52 struct ValidationData {
53 const tcu::IVec4 positions[4];
54 const T values[4];
55 };
56
57 template<typename T>
58 struct ValidationDataStorage {
59 T values;
60 };
61
62 typedef ValidationData<tcu::UVec4> ValidationDataUVec4;
63 typedef ValidationData<tcu::IVec4> ValidationDataIVec4;
64 typedef ValidationData<tcu::Vec4> ValidationDataVec4;
65
66 enum TestType {
67 TYPE_UINT,
68 TYPE_INT,
69 TYPE_FLOAT,
70 };
71
72 enum BufferType {
73 SAMPLER_BUFFER,
74 STORAGE_BUFFER,
75 };
76
77 void initBufferValidatorPrograms (vk::SourceCollections& programCollection, TestType testType, BufferType bufferType);
78 vk::VkDescriptorType getDescriptorType (BufferType bufferType);
79
80 template<typename T>
81 class BufferValidator
82 {
83 public:
BufferValidator(const ValidationData<T> data)84 BufferValidator (const ValidationData<T> data)
85 : m_refData (data)
86 , m_refDataStorage (*reinterpret_cast<ValidationDataStorage<T>*>( &std::vector<char>(sizeof(ValidationDataStorage<T>), '\0').front()))
87 , m_bufferType (SAMPLER_BUFFER)
88 {
89 }
90
BufferValidator(const ValidationDataStorage<T> data)91 BufferValidator (const ValidationDataStorage<T> data)
92 : m_refData (*reinterpret_cast<ValidationData<T>*>( &std::vector<char>(sizeof(ValidationData<T>), '\0').front()))
93 , m_refDataStorage (data)
94 , m_bufferType (STORAGE_BUFFER)
95 {
96 }
97
~BufferValidator()98 ~BufferValidator () {}
99 void initPrograms (vk::SourceCollections& programCollection) const;
100
101 bool validateBuffer (ProtectedContext& ctx,
102 const vk::VkBuffer buffer) const;
103 private:
104 deUint32 getReferenceDataSize () const;
105 const void * getReferenceDataSrc () const;
106 void printReferenceInfo (ProtectedContext& ctx) const;
107
108 const ValidationData<T> m_refData;
109 const ValidationDataStorage<T> m_refDataStorage;
110
111 BufferType m_bufferType;
112 };
113
114 template<>
initPrograms(vk::SourceCollections & programCollection) const115 inline void BufferValidator<tcu::UVec4>::initPrograms (vk::SourceCollections& programCollection) const
116 {
117 initBufferValidatorPrograms(programCollection, TYPE_UINT, m_bufferType);
118 }
119
120 template<>
initPrograms(vk::SourceCollections & programCollection) const121 inline void BufferValidator<tcu::IVec4>::initPrograms (vk::SourceCollections& programCollection) const
122 {
123 initBufferValidatorPrograms(programCollection, TYPE_INT, m_bufferType);
124 }
125
126 template<>
initPrograms(vk::SourceCollections & programCollection) const127 inline void BufferValidator<tcu::Vec4>::initPrograms (vk::SourceCollections& programCollection) const
128 {
129 initBufferValidatorPrograms(programCollection, TYPE_FLOAT, m_bufferType);
130 }
131
132 template<typename T>
getReferenceDataSize() const133 deUint32 BufferValidator<T>::getReferenceDataSize () const
134 {
135 return m_bufferType == SAMPLER_BUFFER ? (deUint32)sizeof(m_refData) : (deUint32)sizeof(m_refDataStorage);
136 }
137
138 template<typename T>
getReferenceDataSrc() const139 const void * BufferValidator<T>::getReferenceDataSrc () const
140 {
141 return m_bufferType == SAMPLER_BUFFER ? (void*)&m_refData : (void*)&m_refDataStorage;
142 }
143
144 template<typename T>
printReferenceInfo(ProtectedContext & ctx) const145 void BufferValidator<T>::printReferenceInfo (ProtectedContext& ctx) const
146 {
147 if (m_bufferType == SAMPLER_BUFFER)
148 {
149 ctx.getTestContext().getLog()
150 << tcu::TestLog::Message << "Reference positions: \n"
151 << "1: " << m_refData.positions[0] << "\n"
152 << "2: " << m_refData.positions[1] << "\n"
153 << "3: " << m_refData.positions[2] << "\n"
154 << "4: " << m_refData.positions[3] << "\n"
155 << tcu::TestLog::EndMessage
156 << tcu::TestLog::Message << "Reference fill values: \n"
157 << "1: " << m_refData.values[0] << "\n"
158 << "2: " << m_refData.values[1] << "\n"
159 << "3: " << m_refData.values[2] << "\n"
160 << "4: " << m_refData.values[3] << "\n"
161 << tcu::TestLog::EndMessage;
162 } else if (m_bufferType == STORAGE_BUFFER)
163 {
164 ctx.getTestContext().getLog()
165 << tcu::TestLog::Message << "Reference values: \n"
166 << "1: " << m_refDataStorage.values << "\n"
167 << tcu::TestLog::EndMessage;
168 }
169 }
170
171 template<typename T>
validateBuffer(ProtectedContext & ctx,const vk::VkBuffer buffer) const172 bool BufferValidator<T>::validateBuffer (ProtectedContext& ctx,
173 const vk::VkBuffer buffer) const
174 {
175 // Log out a few reference info
176 printReferenceInfo(ctx);
177
178 const deUint64 oneSec = 1000 * 1000 * 1000;
179
180 const vk::DeviceInterface& vk = ctx.getDeviceInterface();
181 const vk::VkDevice device = ctx.getDevice();
182 const vk::VkQueue queue = ctx.getQueue();
183 const deUint32 queueFamilyIndex = ctx.getQueueFamilyIndex();
184
185 vk::Move<vk::VkBufferView> bufferView;
186
187 const deUint32 refDataSize = getReferenceDataSize();
188 de::UniquePtr<vk::BufferWithMemory> refUniform (makeBuffer(ctx,
189 PROTECTION_DISABLED,
190 queueFamilyIndex,
191 refDataSize,
192 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
193 vk::MemoryRequirement::HostVisible));
194
195 // Set the reference uniform data
196 {
197 deMemcpy(refUniform->getAllocation().getHostPtr(), getReferenceDataSrc(), refDataSize);
198 vk::flushMappedMemoryRange(vk, device, refUniform->getAllocation().getMemory(), refUniform->getAllocation().getOffset(), refDataSize);
199 }
200
201 const deUint32 helperBufferSize = (deUint32)(2 * sizeof(deUint32));
202 de::MovePtr<vk::BufferWithMemory> helperBuffer (makeBuffer(ctx,
203 PROTECTION_ENABLED,
204 queueFamilyIndex,
205 helperBufferSize,
206 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
207 vk::MemoryRequirement::Protected));
208 vk::Unique<vk::VkShaderModule> resetSSBOShader (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("ResetSSBO"), 0));
209 vk::Unique<vk::VkShaderModule> validatorShader (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("BufferValidator"), 0));
210
211 // Create descriptors
212 vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (vk::DescriptorSetLayoutBuilder()
213 .addSingleBinding(getDescriptorType(m_bufferType), vk::VK_SHADER_STAGE_COMPUTE_BIT)
214 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
215 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
216 .build(vk, device));
217 vk::Unique<vk::VkDescriptorPool> descriptorPool (vk::DescriptorPoolBuilder()
218 .addType(getDescriptorType(m_bufferType), 1u)
219 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
220 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
221 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
222 vk::Unique<vk::VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
223
224
225 // Update descriptor set information
226 {
227 vk::VkDescriptorBufferInfo descRefUniform = makeDescriptorBufferInfo(**refUniform, 0, refDataSize);
228 vk::VkDescriptorBufferInfo descBuffer = makeDescriptorBufferInfo(**helperBuffer, 0, helperBufferSize);
229
230 vk::DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
231 switch (m_bufferType)
232 {
233 case SAMPLER_BUFFER:
234 {
235 const vk::VkBufferViewCreateInfo viewParams =
236 {
237 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType
238 DE_NULL, // const void* pNext
239 0u, // VkBufferViewCreateFlags flags
240 buffer, // VkBuffer buffer
241 vk::VK_FORMAT_R32G32B32A32_UINT, // VkFormat format
242 0u, // VkDeviceSize offset
243 VK_WHOLE_SIZE // VkDeviceSize range
244 };
245 bufferView = vk::Move<vk::VkBufferView> (vk::createBufferView(vk, device, &viewParams));
246 descriptorSetUpdateBuilder
247 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, &bufferView.get());
248 break;
249 }
250 case STORAGE_BUFFER:
251 {
252 const deUint32 testBufferSize = (deUint32)(sizeof(ValidationDataStorage<T>));
253 vk::VkDescriptorBufferInfo descTestBuffer = makeDescriptorBufferInfo(buffer, 0, testBufferSize);
254 descriptorSetUpdateBuilder
255 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descTestBuffer);
256 break;
257 }
258 }
259 descriptorSetUpdateBuilder
260 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descBuffer)
261 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descRefUniform)
262 .update(vk, device);
263 }
264
265 // Build pipeline
266 vk::Unique<vk::VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
267
268 vk::Unique<vk::VkCommandPool> cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
269
270 // Reset helper SSBO
271 {
272 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
273 vk::Unique<vk::VkPipeline> resetSSBOPipeline (makeComputePipeline(vk, device, *pipelineLayout, *resetSSBOShader, DE_NULL));
274 vk::Unique<vk::VkCommandBuffer> resetCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
275 beginCommandBuffer(vk, *resetCmdBuffer);
276
277 vk.cmdBindPipeline(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *resetSSBOPipeline);
278 vk.cmdBindDescriptorSets(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
279 vk.cmdDispatch(*resetCmdBuffer, 1u, 1u, 1u);
280
281 endCommandBuffer(vk, *resetCmdBuffer);
282 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *resetCmdBuffer, *fence, ~0ull));
283 }
284
285 // Create validation compute commands & submit
286 vk::VkResult queueSubmitResult;
287 {
288 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
289 vk::Unique<vk::VkPipeline> validationPipeline (makeComputePipeline(vk, device, *pipelineLayout, *validatorShader, DE_NULL));
290 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
291
292 beginCommandBuffer(vk, *cmdBuffer);
293
294 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *validationPipeline);
295 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
296 vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
297
298 endCommandBuffer(vk, *cmdBuffer);
299
300 queueSubmitResult = queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, oneSec);
301 }
302
303 // \todo do we need to check the fence status?
304 if (queueSubmitResult == vk::VK_TIMEOUT)
305 return false;
306
307 // at this point the submit result should be VK_TRUE
308 VK_CHECK(queueSubmitResult);
309 return true;
310 }
311
312
313 } // ProtectedMem
314 } // vkt
315
316 #endif // _VKTPROTECTEDMEMBUFFERVALIDATOR_HPP
317