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