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 content clear color image tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktProtectedMemClearColorImageTests.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 ClearColorImageTestInstance : public ProtectedTestInstance
58 {
59 public:
60     ClearColorImageTestInstance(Context &ctx, const vk::VkClearColorValue &clearColorValue,
61                                 const ValidationData &refData, 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::VkClearColorValue &m_clearColorValue;
68     const ValidationData &m_refData;
69     const ImageValidator &m_validator;
70     const CmdBufferType m_cmdBufferType;
71 };
72 
73 class ClearColorImageTestCase : public TestCase
74 {
75 public:
ClearColorImageTestCase(tcu::TestContext & testCtx,const std::string & name,vk::VkClearColorValue clearColorValue,ValidationData data,CmdBufferType cmdBufferType)76     ClearColorImageTestCase(tcu::TestContext &testCtx, const std::string &name, vk::VkClearColorValue clearColorValue,
77                             ValidationData data, CmdBufferType cmdBufferType)
78         : TestCase(testCtx, name)
79         , m_clearColorValue(clearColorValue)
80         , m_refData(data)
81         , m_cmdBufferType(cmdBufferType)
82     {
83     }
84 
~ClearColorImageTestCase(void)85     virtual ~ClearColorImageTestCase(void)
86     {
87     }
createInstance(Context & ctx) const88     virtual TestInstance *createInstance(Context &ctx) const
89     {
90         return new ClearColorImageTestInstance(ctx, m_clearColorValue, m_refData, m_validator, m_cmdBufferType);
91     }
initPrograms(vk::SourceCollections & programCollection) const92     virtual void initPrograms(vk::SourceCollections &programCollection) const
93     {
94         m_validator.initPrograms(programCollection);
95     }
checkSupport(Context & context) const96     virtual void checkSupport(Context &context) const
97     {
98         checkProtectedQueueSupport(context);
99 #ifdef CTS_USES_VULKANSC
100         if (m_cmdBufferType == CMD_BUFFER_SECONDARY &&
101             context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
102             TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
103 #endif // CTS_USES_VULKANSC
104     }
105 
106 private:
107     vk::VkClearColorValue m_clearColorValue;
108     ValidationData m_refData;
109     ImageValidator m_validator;
110     CmdBufferType m_cmdBufferType;
111 };
112 
ClearColorImageTestInstance(Context & ctx,const vk::VkClearColorValue & clearColorValue,const ValidationData & refData,const ImageValidator & validator,const CmdBufferType cmdBufferType)113 ClearColorImageTestInstance::ClearColorImageTestInstance(Context &ctx, const vk::VkClearColorValue &clearColorValue,
114                                                          const ValidationData &refData, const ImageValidator &validator,
115                                                          const CmdBufferType cmdBufferType)
116     : ProtectedTestInstance(ctx)
117     , m_imageFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
118     , m_clearColorValue(clearColorValue)
119     , m_refData(refData)
120     , m_validator(validator)
121     , m_cmdBufferType(cmdBufferType)
122 {
123 }
124 
iterate()125 tcu::TestStatus ClearColorImageTestInstance::iterate()
126 {
127     ProtectedContext &ctx(m_protectedContext);
128     const vk::DeviceInterface &vk   = ctx.getDeviceInterface();
129     const vk::VkDevice device       = ctx.getDevice();
130     const vk::VkQueue queue         = ctx.getQueue();
131     const uint32_t queueFamilyIndex = ctx.getQueueFamilyIndex();
132 
133     // Create output image
134     de::MovePtr<vk::ImageWithMemory> colorImage = createImage2D(
135         ctx, PROTECTION_ENABLED, queueFamilyIndex, RENDER_WIDTH, RENDER_HEIGHT, vk::VK_FORMAT_R8G8B8A8_UNORM,
136         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT);
137 
138     vk::Unique<vk::VkPipelineLayout> pipelineLayout(createPipelineLayout(ctx, 0u, DE_NULL));
139 
140     vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
141     vk::Unique<vk::VkCommandBuffer> cmdBuffer(
142         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
143     vk::Unique<vk::VkCommandBuffer> secondaryCmdBuffer(
144         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
145     vk::VkCommandBuffer targetCmdBuffer = (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
146 
147     const vk::VkImageSubresourceRange subresourceRange = {
148         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
149         0u,                            // uint32_t                baseMipLevel
150         1u,                            // uint32_t                levelCount
151         0u,                            // uint32_t                baseArrayLayer
152         1u,                            // uint32_t                layerCount
153     };
154     // Begin cmd buffer
155     beginCommandBuffer(vk, *cmdBuffer);
156 
157     if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
158     {
159         // Begin secondary command buffer
160         const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo = {
161             vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // sType
162             DE_NULL,                                               // pNext
163             DE_NULL,                                               // renderPass
164             0u,                                                    // subpass
165             DE_NULL,                                               // framebuffer
166             VK_FALSE,                                              // occlusionQueryEnable
167             (vk::VkQueryControlFlags)0u,                           // queryFlags
168             (vk::VkQueryPipelineStatisticFlags)0u,                 // pipelineStatistics
169         };
170         beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, bufferInheritanceInfo);
171     }
172 
173     // Start image barrier
174     {
175         const vk::VkImageMemoryBarrier initializeBarrier = {
176             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
177             DE_NULL,                                    // pNext
178             0,                                          // srcAccessMask
179             vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // dstAccessMask
180             vk::VK_IMAGE_LAYOUT_UNDEFINED,              // oldLayout
181             vk::VK_IMAGE_LAYOUT_GENERAL,                // newLayout
182             queueFamilyIndex,                           // srcQueueFamilyIndex
183             queueFamilyIndex,                           // dstQueueFamilyIndex
184             **colorImage,                               // image
185             subresourceRange,                           // subresourceRange
186         };
187 
188         vk.cmdPipelineBarrier(
189             targetCmdBuffer,                               // commandBuffer
190             vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,         // srcStageMask
191             vk::VK_PIPELINE_STAGE_TRANSFER_BIT,            // dstStageMask
192             (vk::VkDependencyFlags)0,                      // dependencyFlags
193             0, (const vk::VkMemoryBarrier *)DE_NULL,       // memoryBarrierCount, pMemoryBarriers
194             0, (const vk::VkBufferMemoryBarrier *)DE_NULL, // bufferMemoryBarrierCount, pBufferMemoryBarriers
195             1, &initializeBarrier);                        // imageMemoryBarrierCount, pImageMemoryBarriers
196     }
197 
198     // Image clear
199     vk.cmdClearColorImage(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_GENERAL, &m_clearColorValue, 1,
200                           &subresourceRange);
201 
202     // Image barrier to change accessMask.
203     {
204         const vk::VkImageMemoryBarrier initializeBarrier = {
205             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // sType
206             DE_NULL,                                      // pNext
207             vk::VK_ACCESS_TRANSFER_WRITE_BIT,             // srcAccessMask
208             vk::VK_ACCESS_SHADER_READ_BIT,                // dstAccessMask
209             vk::VK_IMAGE_LAYOUT_GENERAL,                  // oldLayout
210             vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // newLayout
211             queueFamilyIndex,                             // srcQueueFamilyIndex
212             queueFamilyIndex,                             // dstQueueFamilyIndex
213             **colorImage,                                 // image
214             subresourceRange                              // subresourceRange
215         };
216         vk.cmdPipelineBarrier(targetCmdBuffer,
217                               vk::VK_PIPELINE_STAGE_TRANSFER_BIT,     // srcStageMask
218                               vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, // dstStageMask
219                               (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
220                               (const vk::VkBufferMemoryBarrier *)DE_NULL, 1, &initializeBarrier);
221     }
222 
223     if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
224     {
225         endCommandBuffer(vk, *secondaryCmdBuffer);
226         vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
227     }
228 
229     endCommandBuffer(vk, *cmdBuffer);
230 
231     // Submit command buffer
232     const vk::Unique<vk::VkFence> fence(vk::createFence(vk, device));
233     VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
234 
235     // Log out test data
236     ctx.getTestContext().getLog() << tcu::TestLog::Message
237                                   << "Color clear value: " << tcu::Vec4(m_clearColorValue.float32)
238                                   << tcu::TestLog::EndMessage;
239 
240     // Validate resulting image
241     if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat,
242                                   vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
243         return tcu::TestStatus::pass("Everything went OK");
244     else
245         return tcu::TestStatus::fail("Something went really wrong");
246 }
247 
createClearColorImageTests(tcu::TestContext & testCtx,CmdBufferType cmdBufferType)248 tcu::TestCaseGroup *createClearColorImageTests(tcu::TestContext &testCtx, CmdBufferType cmdBufferType)
249 {
250     struct
251     {
252         vk::VkClearColorValue clearColorValue;
253         ValidationData data;
254     } testData[] = {
255         {{{1.0f, 0.0f, 0.0f, 1.0f}},
256          {{
257               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
258               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
259               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
260               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
261           },
262           {
263               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
264               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
265               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
266               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
267           }}},
268         {{{0.0f, 1.0f, 0.0f, 1.0f}},
269          {{
270               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
271               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
272               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
273               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
274           },
275           {
276               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
277               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
278               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
279               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
280           }}},
281         {{{0.0f, 0.0f, 1.0f, 1.0f}},
282          {{
283               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
284               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
285               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
286               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
287           },
288           {
289               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
290               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
291               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
292               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
293           }}},
294         {{{0.0f, 0.0f, 0.0f, 1.0f}},
295          {{
296               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
297               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
298               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
299               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
300           },
301           {
302               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
303               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
304               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
305               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
306           }}},
307         {{{1.0f, 0.0f, 0.0f, 1.0f}},
308          {{
309               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
310               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
311               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
312               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
313           },
314           {
315               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
316               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
317               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
318               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
319           }}},
320         {{{1.0f, 0.0f, 0.0f, 0.0f}},
321          {{
322               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
323               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
324               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
325               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
326           },
327           {
328               tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
329               tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
330               tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
331               tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
332           }}},
333         {{{0.1f, 0.2f, 0.3f, 0.0f}},
334          {{
335               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
336               tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
337               tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
338               tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
339           },
340           {
341               tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
342               tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
343               tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
344               tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
345           }}},
346     };
347 
348     // Clear Color Image Tests with static input
349     de::MovePtr<tcu::TestCaseGroup> clearStaticTests(new tcu::TestCaseGroup(testCtx, "static"));
350 
351     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
352     {
353         const std::string name = "clear_" + de::toString(ndx + 1);
354         clearStaticTests->addChild(new ClearColorImageTestCase(testCtx, name.c_str(), testData[ndx].clearColorValue,
355                                                                testData[ndx].data, cmdBufferType));
356     }
357 
358     /* Add a few randomized tests */
359     // Clear Color Image Tests with random input
360     de::MovePtr<tcu::TestCaseGroup> clearRandomTests(new tcu::TestCaseGroup(testCtx, "random"));
361     const int testCount = 10;
362     de::Random rnd(testCtx.getCommandLine().getBaseSeed());
363     for (int ndx = 0; ndx < testCount; ++ndx)
364     {
365         const std::string name      = "clear_" + de::toString(ndx + 1);
366         vk::VkClearValue clearValue = vk::makeClearValueColorVec4(tcu::randomVec4(rnd));
367         const tcu::Vec4 refValue(clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2],
368                                  clearValue.color.float32[3]);
369         const tcu::Vec4 vec0 = tcu::randomVec4(rnd);
370         const tcu::Vec4 vec1 = tcu::randomVec4(rnd);
371         const tcu::Vec4 vec2 = tcu::randomVec4(rnd);
372         const tcu::Vec4 vec3 = tcu::randomVec4(rnd);
373 
374         ValidationData data = {{vec0, vec1, vec2, vec3}, {refValue, refValue, refValue, refValue}};
375         clearRandomTests->addChild(
376             new ClearColorImageTestCase(testCtx, name.c_str(), clearValue.color, data, cmdBufferType));
377     }
378 
379     std::string groupName = getCmdBufferTypeStr(cmdBufferType);
380     de::MovePtr<tcu::TestCaseGroup> clearTests(new tcu::TestCaseGroup(testCtx, groupName.c_str()));
381     clearTests->addChild(clearStaticTests.release());
382     clearTests->addChild(clearRandomTests.release());
383     return clearTests.release();
384 }
385 
386 } // namespace
387 
createClearColorImageTests(tcu::TestContext & testCtx)388 tcu::TestCaseGroup *createClearColorImageTests(tcu::TestContext &testCtx)
389 {
390     de::MovePtr<tcu::TestCaseGroup> clearTests(new tcu::TestCaseGroup(testCtx, "clear_color"));
391 
392     clearTests->addChild(createClearColorImageTests(testCtx, CMD_BUFFER_PRIMARY));
393     clearTests->addChild(createClearColorImageTests(testCtx, CMD_BUFFER_SECONDARY));
394 
395     return clearTests.release();
396 }
397 
398 } // namespace ProtectedMem
399 } // namespace vkt
400