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 attachment clear tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktProtectedMemAttachmentClearTests.hpp"
26
27 #include "deRandom.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuVector.hpp"
30
31 #include "vkPrograms.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestGroupUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkCmdUtil.hpp"
37
38 #include "vktProtectedMemContext.hpp"
39 #include "vktProtectedMemUtils.hpp"
40 #include "vktProtectedMemImageValidator.hpp"
41
42 namespace vkt
43 {
44 namespace ProtectedMem
45 {
46
47 namespace
48 {
49
50 enum {
51 RENDER_WIDTH = 128,
52 RENDER_HEIGHT = 128,
53 };
54
55 class AttachmentClearTestInstance : public ProtectedTestInstance
56 {
57 public:
58 AttachmentClearTestInstance (Context& ctx,
59 const vk::VkClearValue& clearValue,
60 const ValidationData& refData,
61 const ImageValidator& validator,
62 const CmdBufferType cmdBufferType);
63 virtual tcu::TestStatus iterate (void);
64
65 private:
66 const vk::VkFormat m_imageFormat;
67 const vk::VkClearValue& m_clearValue;
68 const ValidationData& m_refData;
69 const ImageValidator& m_validator;
70 const CmdBufferType m_cmdBufferType;
71 };
72
73
74 class AttachmentClearTestCase : public TestCase
75 {
76 public:
AttachmentClearTestCase(tcu::TestContext & testCtx,const std::string & name,vk::VkClearValue clearValue,ValidationData data,CmdBufferType cmdBufferType)77 AttachmentClearTestCase (tcu::TestContext& testCtx,
78 const std::string& name,
79 vk::VkClearValue clearValue,
80 ValidationData data,
81 CmdBufferType cmdBufferType)
82 : TestCase (testCtx, name, "Clear attachment.")
83 , m_clearValue (clearValue)
84 , m_refData (data)
85 , m_cmdBufferType (cmdBufferType)
86 {
87 }
88
~AttachmentClearTestCase(void)89 virtual ~AttachmentClearTestCase (void) {}
createInstance(Context & ctx) const90 virtual TestInstance* createInstance (Context& ctx) const
91 {
92 return new AttachmentClearTestInstance(ctx, m_clearValue, m_refData, m_validator, m_cmdBufferType);
93 }
initPrograms(vk::SourceCollections & programCollection) const94 virtual void initPrograms (vk::SourceCollections& programCollection) const
95 {
96 m_validator.initPrograms(programCollection);
97 }
98 private:
99 vk::VkClearValue m_clearValue;
100 ValidationData m_refData;
101 ImageValidator m_validator;
102 CmdBufferType m_cmdBufferType;
103 };
104
AttachmentClearTestInstance(Context & ctx,const vk::VkClearValue & clearValue,const ValidationData & refData,const ImageValidator & validator,const CmdBufferType cmdBufferType)105 AttachmentClearTestInstance::AttachmentClearTestInstance (Context& ctx,
106 const vk::VkClearValue& clearValue,
107 const ValidationData& refData,
108 const ImageValidator& validator,
109 const CmdBufferType cmdBufferType)
110 : ProtectedTestInstance (ctx)
111 , m_imageFormat (vk::VK_FORMAT_R8G8B8A8_UNORM)
112 , m_clearValue (clearValue)
113 , m_refData (refData)
114 , m_validator (validator)
115 , m_cmdBufferType (cmdBufferType)
116 {
117 }
118
iterate()119 tcu::TestStatus AttachmentClearTestInstance::iterate()
120 {
121 ProtectedContext& ctx (m_protectedContext);
122 const vk::DeviceInterface& vk = ctx.getDeviceInterface();
123 const vk::VkDevice device = ctx.getDevice();
124 const vk::VkQueue queue = ctx.getQueue();
125 const deUint32 queueFamilyIndex = ctx.getQueueFamilyIndex();
126
127 // Create output image
128 de::MovePtr<vk::ImageWithMemory> colorImage (createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
129 RENDER_WIDTH, RENDER_HEIGHT,
130 m_imageFormat,
131 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_SAMPLED_BIT));
132 vk::Unique<vk::VkImageView> colorImageView (createImageView(ctx, **colorImage, m_imageFormat));
133
134 vk::Unique<vk::VkRenderPass> renderPass (createRenderPass(ctx, m_imageFormat));
135 vk::Unique<vk::VkFramebuffer> framebuffer (createFramebuffer(ctx, RENDER_WIDTH, RENDER_HEIGHT, *renderPass, *colorImageView));
136 vk::Unique<vk::VkPipelineLayout> pipelineLayout (createPipelineLayout(ctx, 0u, DE_NULL));
137
138 vk::Unique<vk::VkCommandPool> cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
139 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
140 vk::Unique<vk::VkCommandBuffer> secondaryCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
141 vk::VkCommandBuffer targetCmdBuffer = (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
142
143 // Begin cmd buffer
144 beginCommandBuffer(vk, *cmdBuffer);
145
146 // Start image barrier
147 {
148 const vk::VkImageMemoryBarrier startImgBarrier =
149 {
150 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
151 DE_NULL, // pNext
152 0, // srcAccessMask
153 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
154 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
155 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
156 queueFamilyIndex, // srcQueueFamilyIndex
157 queueFamilyIndex, // dstQueueFamilyIndex
158 **colorImage, // image
159 {
160 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
161 0u, // baseMipLevel
162 1u, // mipLevels
163 0u, // baseArraySlice
164 1u, // subresourceRange
165 }
166 };
167
168 vk.cmdPipelineBarrier(*cmdBuffer,
169 vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
170 vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
171 (vk::VkDependencyFlags)0,
172 0, (const vk::VkMemoryBarrier*)DE_NULL,
173 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
174 1, &startImgBarrier);
175 }
176
177 // Image clear to different from input color
178
179 const tcu::Vec4 clearValue (m_clearValue.color.float32[0] < 0.5f ? 1.0f : 0.0f,
180 m_clearValue.color.float32[1] < 0.5f ? 1.0f : 0.0f,
181 m_clearValue.color.float32[2] < 0.5f ? 1.0f : 0.0f,
182 m_clearValue.color.float32[3] < 0.5f ? 1.0f : 0.0f);
183
184 const vk::VkSubpassContents subpassContents = m_cmdBufferType == CMD_BUFFER_SECONDARY
185 ? vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
186 : vk::VK_SUBPASS_CONTENTS_INLINE;
187 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, vk::makeRect2D(RENDER_WIDTH, RENDER_HEIGHT), clearValue, subpassContents);
188
189 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
190 {
191 // Begin secondary command buffer
192 const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo =
193 {
194 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // sType
195 DE_NULL, // pNext
196 *renderPass, // renderPass
197 0u, // subpass
198 *framebuffer, // framebuffer
199 VK_FALSE, // occlusionQueryEnable
200 (vk::VkQueryControlFlags)0u, // queryFlags
201 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
202 };
203 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, bufferInheritanceInfo);
204 }
205
206 {
207 const vk::VkClearAttachment pAttachments =
208 {
209 vk::VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask
210 0u, //uint32_t colorAttachment
211 m_clearValue // VkClearValue clearValue;
212 };
213 const vk::VkRect2D rect2D = vk::makeRect2D(RENDER_WIDTH, RENDER_HEIGHT);
214 const vk::VkClearRect clearRect =
215 {
216 rect2D, // VkRect2D rect;
217 0u, // deUint32 baseArrayLayer;
218 1u // deUint32 layerCount;
219 };
220 vk.cmdClearAttachments(targetCmdBuffer, 1u, &pAttachments, 1u, &clearRect);
221 }
222
223 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
224 {
225 endCommandBuffer(vk, *secondaryCmdBuffer);
226 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
227 }
228
229 endRenderPass(vk, *cmdBuffer);
230
231 {
232 // Image validator reads image in compute shader
233 const vk::VkImageMemoryBarrier endImgBarrier =
234 {
235 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
236 DE_NULL, // pNext
237 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
238 vk::VK_ACCESS_SHADER_READ_BIT, // dstAccessMask
239 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
240 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // newLayout
241 queueFamilyIndex, // srcQueueFamilyIndex
242 queueFamilyIndex, // dstQueueFamilyIndex
243 **colorImage, // image
244 {
245 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
246 0u, // baseMipLevel
247 1u, // mipLevels
248 0u, // baseArraySlice
249 1u, // subresourceRange
250 }
251 };
252 vk.cmdPipelineBarrier(*cmdBuffer,
253 vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
254 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
255 (vk::VkDependencyFlags)0,
256 0, (const vk::VkMemoryBarrier*)DE_NULL,
257 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
258 1, &endImgBarrier);
259 }
260
261 endCommandBuffer(vk, *cmdBuffer);
262
263 // Submit command buffer
264 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
265 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
266
267 // Log out test data
268 ctx.getTestContext().getLog()
269 << tcu::TestLog::Message << "Color clear value: " << tcu::Vec4(m_clearValue.color.float32) << tcu::TestLog::EndMessage
270 << tcu::TestLog::Message << "Depth clear value: " << m_clearValue.depthStencil.depth << tcu::TestLog::EndMessage
271 << tcu::TestLog::Message << "Stencil clear value: " << m_clearValue.depthStencil.stencil << tcu::TestLog::EndMessage;
272
273 // Validate resulting image
274 if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
275 return tcu::TestStatus::pass("Everything went OK");
276 else
277 return tcu::TestStatus::fail("Something went really wrong");
278 }
279
createAttachmentClearTests(tcu::TestContext & testCtx,CmdBufferType cmdBufferType)280 tcu::TestCaseGroup* createAttachmentClearTests (tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
281 {
282 struct {
283 const vk::VkClearValue clearValue;
284 const ValidationData data;
285 } testData[] = {
286 { vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f),
287 {
288 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
289 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
290 { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
291 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
292 }
293 },
294 { vk::makeClearValueColorF32(0.0f, 1.0f, 0.0f, 1.0f),
295 {
296 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
297 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
298 { tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
299 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), }
300 }
301 },
302 { vk::makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f),
303 {
304 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
305 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
306 { tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
307 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), }
308 }
309 },
310 { vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f),
311 {
312 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
313 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
314 { tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
315 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), }
316 }
317 },
318 { vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f),
319 {
320 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
321 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
322 { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
323 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
324 }
325 },
326 { vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 0.0f),
327 {
328 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
329 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
330 { tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
331 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), }
332 }
333 },
334 { vk::makeClearValueColorF32(0.1f, 0.2f, 0.3f, 0.0f),
335 {
336 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
337 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
338 { tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
339 tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), }
340 }
341 },
342 };
343
344 de::MovePtr<tcu::TestCaseGroup> clearStaticTests (new tcu::TestCaseGroup(testCtx, "static", "Attachment Clear Op Tests with static input"));
345
346 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
347 {
348 const std::string name = "clear_" + de::toString(ndx + 1);
349 clearStaticTests->addChild(new AttachmentClearTestCase(testCtx, name.c_str(), testData[ndx].clearValue, testData[ndx].data, cmdBufferType));
350 }
351
352 /* Add a few randomized tests */
353 de::MovePtr<tcu::TestCaseGroup> clearRandomTests (new tcu::TestCaseGroup(testCtx, "random", "Attachment Clear Op Tests with random input"));
354 const int testCount = 10;
355 de::Random rnd (testCtx.getCommandLine().getBaseSeed());
356 for (int ndx = 0; ndx < testCount; ++ndx)
357 {
358 const std::string name = "clear_" + de::toString(ndx + 1);
359 vk::VkClearValue clearValue = vk::makeClearValueColorF32(
360 rnd.getFloat(0.0, 1.0f),
361 rnd.getFloat(0.0, 1.0f),
362 rnd.getFloat(0.0, 1.0f),
363 rnd.getFloat(0.0, 1.0f));
364
365 tcu::Vec4 refValue (clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]);
366 ValidationData data =
367 {
368 { tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)),
369 tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)),
370 tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)),
371 tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)) },
372 { refValue, refValue, refValue, refValue }
373 };
374
375 clearRandomTests->addChild(new AttachmentClearTestCase(testCtx, name.c_str(), clearValue, data, cmdBufferType));
376 }
377
378 std::string groupName = getCmdBufferTypeStr(cmdBufferType);
379 std::string groupDesc = "Attachment Clear Op Tests with " + groupName + " command buffer";
380 de::MovePtr<tcu::TestCaseGroup> clearTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
381 clearTests->addChild(clearStaticTests.release());
382 clearTests->addChild(clearRandomTests.release());
383 return clearTests.release();
384 }
385
386 } // anonymous
387
createAttachmentClearTests(tcu::TestContext & testCtx)388 tcu::TestCaseGroup* createAttachmentClearTests (tcu::TestContext& testCtx)
389 {
390 de::MovePtr<tcu::TestCaseGroup> clearTests (new tcu::TestCaseGroup(testCtx, "clear_op", "Attachment Clear Op Tests"));
391
392 clearTests->addChild(createAttachmentClearTests(testCtx, CMD_BUFFER_PRIMARY));
393 clearTests->addChild(createAttachmentClearTests(testCtx, CMD_BUFFER_SECONDARY));
394
395 return clearTests.release();
396 }
397
398 } // ProtectedMem
399 } // vkt
400