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 render pass load tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktProtectedMemAttachmentLoadTests.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 AttachmentLoadTestInstance : public ProtectedTestInstance
58 {
59 public:
60     AttachmentLoadTestInstance(Context &ctx, const vk::VkClearValue &clearValue, const ValidationData &refData,
61                                const ImageValidator &validator);
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 };
70 
71 class AttachmentLoadTestCase : public TestCase
72 {
73 public:
AttachmentLoadTestCase(tcu::TestContext & testCtx,const std::string & name,vk::VkClearValue clearValue,ValidationData data)74     AttachmentLoadTestCase(tcu::TestContext &testCtx, const std::string &name, vk::VkClearValue clearValue,
75                            ValidationData data)
76         : TestCase(testCtx, name)
77         , m_clearValue(clearValue)
78         , m_refData(data)
79     {
80     }
81 
~AttachmentLoadTestCase(void)82     virtual ~AttachmentLoadTestCase(void)
83     {
84     }
createInstance(Context & ctx) const85     virtual TestInstance *createInstance(Context &ctx) const
86     {
87         return new AttachmentLoadTestInstance(ctx, m_clearValue, m_refData, m_validator);
88     }
initPrograms(vk::SourceCollections & programCollection) const89     virtual void initPrograms(vk::SourceCollections &programCollection) const
90     {
91         m_validator.initPrograms(programCollection);
92     }
checkSupport(Context & context) const93     virtual void checkSupport(Context &context) const
94     {
95         checkProtectedQueueSupport(context);
96     }
97 
98 private:
99     vk::VkClearValue m_clearValue;
100     ValidationData m_refData;
101     ImageValidator m_validator;
102 };
103 
AttachmentLoadTestInstance(Context & ctx,const vk::VkClearValue & clearValue,const ValidationData & refData,const ImageValidator & validator)104 AttachmentLoadTestInstance::AttachmentLoadTestInstance(Context &ctx, const vk::VkClearValue &clearValue,
105                                                        const ValidationData &refData, const ImageValidator &validator)
106     : ProtectedTestInstance(ctx)
107     , m_imageFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
108     , m_clearValue(clearValue)
109     , m_refData(refData)
110     , m_validator(validator)
111 {
112 }
113 
iterate()114 tcu::TestStatus AttachmentLoadTestInstance::iterate()
115 {
116     ProtectedContext &ctx(m_protectedContext);
117     const vk::DeviceInterface &vk   = ctx.getDeviceInterface();
118     const vk::VkDevice device       = ctx.getDevice();
119     const vk::VkQueue queue         = ctx.getQueue();
120     const uint32_t queueFamilyIndex = ctx.getQueueFamilyIndex();
121 
122     // Create output image
123     de::MovePtr<vk::ImageWithMemory> colorImage(
124         createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex, RENDER_WIDTH, RENDER_HEIGHT, m_imageFormat,
125                       vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT));
126     vk::Unique<vk::VkImageView> colorImageView(createImageView(ctx, **colorImage, m_imageFormat));
127 
128     vk::Unique<vk::VkRenderPass> renderPass(createRenderPass(ctx, m_imageFormat));
129     vk::Unique<vk::VkFramebuffer> framebuffer(
130         createFramebuffer(ctx, RENDER_WIDTH, RENDER_HEIGHT, *renderPass, *colorImageView));
131     vk::Unique<vk::VkPipelineLayout> pipelineLayout(createPipelineLayout(ctx, 0u, DE_NULL));
132 
133     vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
134     vk::Unique<vk::VkCommandBuffer> cmdBuffer(
135         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
136 
137     // Begin cmd buffer
138     beginCommandBuffer(vk, *cmdBuffer);
139 
140     // Start image barrier
141     {
142         const vk::VkImageMemoryBarrier startImgBarrier = {vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // sType
143                                                           DE_NULL,                                      // pNext
144                                                           0,                                            // srcAccessMask
145                                                           vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // dstAccessMask
146                                                           vk::VK_IMAGE_LAYOUT_UNDEFINED,                // oldLayout
147                                                           vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
148                                                           queueFamilyIndex, // srcQueueFamilyIndex
149                                                           queueFamilyIndex, // dstQueueFamilyIndex
150                                                           **colorImage,     // image
151                                                           {
152                                                               vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
153                                                               0u,                            // baseMipLevel
154                                                               1u,                            // mipLevels
155                                                               0u,                            // baseArraySlice
156                                                               1u,                            // subresourceRange
157                                                           }};
158 
159         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
160                               (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
161                               (const vk::VkBufferMemoryBarrier *)DE_NULL, 1, &startImgBarrier);
162     }
163 
164     // Image clear
165     beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, vk::makeRect2D(0, 0, RENDER_WIDTH, RENDER_HEIGHT),
166                     m_clearValue);
167     endRenderPass(vk, *cmdBuffer);
168 
169     {
170         // Image validator reads image in compute shader
171         const vk::VkImageMemoryBarrier endImgBarrier = {vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // sType
172                                                         DE_NULL,                                      // pNext
173                                                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // srcAccessMask
174                                                         vk::VK_ACCESS_SHADER_READ_BIT,                // dstAccessMask
175                                                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
176                                                         vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // newLayout
177                                                         queueFamilyIndex, // srcQueueFamilyIndex
178                                                         queueFamilyIndex, // dstQueueFamilyIndex
179                                                         **colorImage,     // image
180                                                         {
181                                                             vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
182                                                             0u,                            // baseMipLevel
183                                                             1u,                            // mipLevels
184                                                             0u,                            // baseArraySlice
185                                                             1u,                            // subresourceRange
186                                                         }};
187         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
188                               vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (vk::VkDependencyFlags)0, 0,
189                               (const vk::VkMemoryBarrier *)DE_NULL, 0, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1,
190                               &endImgBarrier);
191     }
192 
193     endCommandBuffer(vk, *cmdBuffer);
194 
195     // Submit command buffer
196     const vk::Unique<vk::VkFence> fence(vk::createFence(vk, device));
197     VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
198 
199     // Log out test data
200     ctx.getTestContext().getLog() << tcu::TestLog::Message
201                                   << "Color clear value: " << tcu::Vec4(m_clearValue.color.float32)
202                                   << tcu::TestLog::EndMessage << tcu::TestLog::Message
203                                   << "Depth clear value: " << m_clearValue.depthStencil.depth
204                                   << tcu::TestLog::EndMessage << tcu::TestLog::Message
205                                   << "Stencil clear value: " << m_clearValue.depthStencil.stencil
206                                   << tcu::TestLog::EndMessage;
207 
208     // Validate resulting image
209     if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat,
210                                   vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
211         return tcu::TestStatus::pass("Everything went OK");
212     else
213         return tcu::TestStatus::fail("Something went really wrong");
214 }
215 
216 } // namespace
217 
createAttachmentLoadTests(tcu::TestContext & testCtx)218 tcu::TestCaseGroup *createAttachmentLoadTests(tcu::TestContext &testCtx)
219 {
220     struct
221     {
222         const vk::VkClearValue clearValue;
223         const ValidationData data;
224     } testData[] = {
225         {vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f),
226          {{
227               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
228               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
229               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
230               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
231           },
232           {
233               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
234               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
235               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
236               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
237           }}},
238         {vk::makeClearValueColorF32(0.0f, 1.0f, 0.0f, 1.0f),
239          {{
240               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
241               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
242               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
243               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
244           },
245           {
246               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
247               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
248               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
249               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
250           }}},
251         {vk::makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f),
252          {{
253               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
254               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
255               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
256               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
257           },
258           {
259               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
260               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
261               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
262               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
263           }}},
264         {vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f),
265          {{
266               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
267               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
268               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
269               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
270           },
271           {
272               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
273               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
274               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
275               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
276           }}},
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(1.0f, 0.0f, 0.0f, 0.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(1.0f, 0.0f, 0.0f, 0.0f),
299               tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
300               tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
301               tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
302           }}},
303         {vk::makeClearValueColorF32(0.1f, 0.2f, 0.3f, 0.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.1f, 0.2f, 0.3f, 0.0f),
312               tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
313               tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
314               tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
315           }}},
316     };
317 
318     // Attachment Load Op Tests with static input
319     de::MovePtr<tcu::TestCaseGroup> loadStaticTests(new tcu::TestCaseGroup(testCtx, "static"));
320 
321     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
322     {
323         const std::string name = "clear_" + de::toString(ndx + 1);
324         loadStaticTests->addChild(
325             new AttachmentLoadTestCase(testCtx, name.c_str(), testData[ndx].clearValue, testData[ndx].data));
326     }
327 
328     /* Add a few randomized tests */
329     // Attachment Load Op Tests with random input
330     de::MovePtr<tcu::TestCaseGroup> loadRandomTests(new tcu::TestCaseGroup(testCtx, "random"));
331     const int testCount = 10;
332     de::Random rnd(testCtx.getCommandLine().getBaseSeed());
333     for (int ndx = 0; ndx < testCount; ++ndx)
334     {
335         const std::string name      = "clear_" + de::toString(ndx + 1);
336         vk::VkClearValue clearValue = vk::makeClearValueColorVec4(tcu::randomVec4(rnd));
337         const tcu::Vec4 refValue(clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2],
338                                  clearValue.color.float32[3]);
339         const tcu::Vec4 vec0 = tcu::randomVec4(rnd);
340         const tcu::Vec4 vec1 = tcu::randomVec4(rnd);
341         const tcu::Vec4 vec2 = tcu::randomVec4(rnd);
342         const tcu::Vec4 vec3 = tcu::randomVec4(rnd);
343 
344         ValidationData data = {{vec0, vec1, vec2, vec3}, {refValue, refValue, refValue, refValue}};
345 
346         loadRandomTests->addChild(new AttachmentLoadTestCase(testCtx, name.c_str(), clearValue, data));
347     }
348 
349     de::MovePtr<tcu::TestCaseGroup> loadTests(new tcu::TestCaseGroup(testCtx, "load_op"));
350     loadTests->addChild(loadStaticTests.release());
351     loadTests->addChild(loadRandomTests.release());
352     return loadTests.release();
353 }
354 
355 } // namespace ProtectedMem
356 } // namespace vkt
357