1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017 The Khronos Group Inc.
6 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Protected content copy image tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktProtectedMemCopyImageTests.hpp"
27 #include "deRandom.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuVector.hpp"
30 #include "tcuVectorUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestGroupUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkCmdUtil.hpp"
39 #include "vktProtectedMemContext.hpp"
40 #include "vktProtectedMemUtils.hpp"
41 #include "vktProtectedMemImageValidator.hpp"
45 namespace ProtectedMem
56 class CopyImageTestInstance : public ProtectedTestInstance
59 CopyImageTestInstance (Context& ctx,
60 const vk::VkClearColorValue& clearColorValue,
61 const ValidationData& refData,
62 const ImageValidator& validator,
63 const CmdBufferType cmdBufferType);
64 virtual tcu::TestStatus iterate (void);
67 const vk::VkFormat m_imageFormat;
68 const vk::VkClearColorValue& m_clearColorValue;
69 const ValidationData& m_refData;
70 const ImageValidator& m_validator;
71 const CmdBufferType m_cmdBufferType;
74 class CopyImageTestCase : public TestCase
77 CopyImageTestCase (tcu::TestContext& testCtx,
78 const std::string& name,
79 vk::VkClearColorValue clearColorValue,
81 CmdBufferType cmdBufferType)
82 : TestCase (testCtx, name, "Clear and copy image.")
83 , m_clearColorValue (clearColorValue)
85 , m_cmdBufferType (cmdBufferType)
89 virtual ~CopyImageTestCase (void) {}
90 virtual TestInstance* createInstance (Context& ctx) const
92 return new CopyImageTestInstance(ctx, m_clearColorValue, m_refData, m_validator, m_cmdBufferType);
94 virtual void initPrograms (vk::SourceCollections& programCollection) const
96 m_validator.initPrograms(programCollection);
99 vk::VkClearColorValue m_clearColorValue;
100 ValidationData m_refData;
101 ImageValidator m_validator;
102 CmdBufferType m_cmdBufferType;
105 CopyImageTestInstance::CopyImageTestInstance (Context& ctx,
106 const vk::VkClearColorValue& clearColorValue,
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_clearColorValue (clearColorValue)
113 , m_refData (refData)
114 , m_validator (validator)
115 , m_cmdBufferType (cmdBufferType)
119 tcu::TestStatus CopyImageTestInstance::iterate()
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();
128 de::MovePtr<vk::ImageWithMemory> colorImage = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
129 RENDER_WIDTH, RENDER_HEIGHT,
131 vk::VK_IMAGE_USAGE_SAMPLED_BIT
132 | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
133 de::MovePtr<vk::ImageWithMemory> colorImageSrc = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
134 RENDER_WIDTH, RENDER_HEIGHT,
136 vk::VK_IMAGE_USAGE_SAMPLED_BIT
137 | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT
138 | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
140 vk::Unique<vk::VkPipelineLayout> pipelineLayout (createPipelineLayout(ctx, 0u, DE_NULL));
142 vk::Unique<vk::VkCommandPool> cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
143 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
144 vk::Unique<vk::VkCommandBuffer> secondaryCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
145 vk::VkCommandBuffer targetCmdBuffer = (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
148 beginCommandBuffer(vk, *cmdBuffer);
150 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
152 // Begin secondary command buffer
153 const vk::VkCommandBufferInheritanceInfo secCmdBufInheritInfo =
155 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
157 (vk::VkRenderPass)0u, // renderPass
159 (vk::VkFramebuffer)0u, // framebuffer
160 VK_FALSE, // occlusionQueryEnable
161 (vk::VkQueryControlFlags)0u, // queryFlags
162 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
164 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, secCmdBufInheritInfo);
167 // Start image barrier for source image.
169 const vk::VkImageMemoryBarrier startImgBarrier =
171 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
174 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask
175 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
176 vk::VK_IMAGE_LAYOUT_GENERAL, // newLayout
177 queueFamilyIndex, // srcQueueFamilyIndex
178 queueFamilyIndex, // dstQueueFamilyIndex
179 **colorImageSrc, // image
181 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
184 0u, // baseArraySlice
185 1u, // subresourceRange
189 vk.cmdPipelineBarrier(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, &startImgBarrier); // imageMemoryBarrierCount, pImageMemoryBarriers
199 const vk::VkImageSubresourceRange subresourceRange =
201 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
202 0u, // uint32_t baseMipLevel
203 1u, // uint32_t levelCount
204 0u, // uint32_t baseArrayLayer
205 1u, // uint32_t layerCount
207 vk.cmdClearColorImage(targetCmdBuffer, **colorImageSrc, vk::VK_IMAGE_LAYOUT_GENERAL, &m_clearColorValue, 1, &subresourceRange);
209 // Image barrier to change accessMask to transfer read bit for source image.
211 const vk::VkImageMemoryBarrier initializeBarrier =
213 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
215 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
216 vk::VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask
217 vk::VK_IMAGE_LAYOUT_GENERAL, // oldLayout
218 vk::VK_IMAGE_LAYOUT_GENERAL, // newLayout
219 queueFamilyIndex, // srcQueueFamilyIndex
220 queueFamilyIndex, // dstQueueFamilyIndex
221 **colorImageSrc, // image
223 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
226 0u, // baseArraySlice
227 1u, // subresourceRange
231 vk.cmdPipelineBarrier(targetCmdBuffer,
232 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask
233 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, // dstStageMask
234 (vk::VkDependencyFlags)0,
235 0, (const vk::VkMemoryBarrier*)DE_NULL,
236 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
237 1, &initializeBarrier);
240 // Image barrier for destination image.
242 const vk::VkImageMemoryBarrier initializeBarrier =
244 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
247 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask
248 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
249 vk::VK_IMAGE_LAYOUT_GENERAL, // newLayout
250 queueFamilyIndex, // srcQueueFamilyIndex
251 queueFamilyIndex, // dstQueueFamilyIndex
252 **colorImage, // image
254 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
257 0u, // baseArraySlice
258 1u, // subresourceRange
262 vk.cmdPipelineBarrier(targetCmdBuffer,
263 vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // srcStageMask
264 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, // dstStageMask
265 (vk::VkDependencyFlags)0,
266 0, (const vk::VkMemoryBarrier*)DE_NULL,
267 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
268 1, &initializeBarrier);
272 const vk::VkImageSubresourceLayers imgSubResCopy =
274 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
275 0u, // deUint32 mipLevel;
276 0u, // deUint32 baseArrayLayer;
277 1u, // deUint32 layerCount;
279 const vk::VkOffset3D nullOffset = {0u, 0u, 0u};
280 const vk::VkExtent3D imageExtent = {(deUint32)RENDER_WIDTH, (deUint32)RENDER_HEIGHT, 1u};
281 const vk::VkImageCopy copyImageRegion =
283 imgSubResCopy, // VkImageSubresourceCopy srcSubresource;
284 nullOffset, // VkOffset3D srcOffset;
285 imgSubResCopy, // VkImageSubresourceCopy destSubresource;
286 nullOffset, // VkOffset3D destOffset;
287 imageExtent, // VkExtent3D extent;
290 vk.cmdCopyImage(targetCmdBuffer,
291 **colorImageSrc, vk::VK_IMAGE_LAYOUT_GENERAL, // srcImageLayout
292 **colorImage, vk::VK_IMAGE_LAYOUT_GENERAL, // dstImageLayout
293 1u, ©ImageRegion);
295 // Image barrier to change accessMask for destination image.
297 const vk::VkImageMemoryBarrier endImgBarrier =
299 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
301 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
302 vk::VK_ACCESS_SHADER_READ_BIT, // dstAccessMask
303 vk::VK_IMAGE_LAYOUT_GENERAL, // oldLayout
304 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // newLayout
305 queueFamilyIndex, // srcQueueFamilyIndex
306 queueFamilyIndex, // dstQueueFamilyIndex
307 **colorImage, // image
309 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
312 0u, // baseArraySlice
313 1u, // subresourceRange
316 vk.cmdPipelineBarrier(targetCmdBuffer,
317 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask
318 vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, // dstStageMask
319 (vk::VkDependencyFlags)0,
320 0, (const vk::VkMemoryBarrier*)DE_NULL,
321 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
325 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
327 endCommandBuffer(vk, *secondaryCmdBuffer);
328 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
331 endCommandBuffer(vk, *cmdBuffer);
333 // Submit command buffer
334 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
335 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
338 ctx.getTestContext().getLog()
339 << tcu::TestLog::Message << "Color clear value: " << tcu::Vec4(m_clearColorValue.float32) << tcu::TestLog::EndMessage;
341 // Validate resulting image
342 if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
343 return tcu::TestStatus::pass("Everything went OK");
345 return tcu::TestStatus::fail("Something went really wrong");
348 tcu::TestCaseGroup* createCopyImageTests (tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
351 const vk::VkClearColorValue clearColorValue;
352 const ValidationData data;
354 { { { 1.0f, 0.0f, 0.0f, 1.0f } },
356 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
357 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
358 { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
359 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
362 { { { 0.0f, 1.0f, 0.0f, 1.0f } },
364 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
365 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
366 { tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
367 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), }
370 { { { 0.0f, 0.0f, 1.0f, 1.0f } },
372 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
373 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
374 { tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
375 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), }
378 { { { 0.0f, 0.0f, 0.0f, 1.0f } },
380 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
381 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
382 { tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
383 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), }
386 { { { 1.0f, 0.0f, 0.0f, 1.0f } },
388 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
389 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
390 { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
391 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
394 { { { 1.0f, 0.0f, 0.0f, 0.0f } },
396 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
397 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
398 { tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
399 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), }
402 { { { 0.1f, 0.2f, 0.3f, 0.0f } },
404 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
405 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
406 { tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
407 tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), }
412 de::MovePtr<tcu::TestCaseGroup> copyStaticTests (new tcu::TestCaseGroup(testCtx, "static", "Copy Image Tests with static input"));
414 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
416 const std::string name = "copy_" + de::toString(ndx + 1);
417 copyStaticTests->addChild(new CopyImageTestCase(testCtx, name.c_str(), testData[ndx].clearColorValue, testData[ndx].data, cmdBufferType));
420 /* Add a few randomized tests */
421 de::MovePtr<tcu::TestCaseGroup> copyRandomTests (new tcu::TestCaseGroup(testCtx, "random", "Copy Image Tests with random input"));
422 const int testCount = 10;
423 de::Random rnd (testCtx.getCommandLine().getBaseSeed());
424 for (int ndx = 0; ndx < testCount; ++ndx)
426 const std::string name = "copy_" + de::toString(ndx + 1);
427 vk::VkClearValue clearValue = vk::makeClearValueColorVec4(tcu::randomVec4(rnd));
428 const tcu::Vec4 refValue (clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]);
429 const tcu::Vec4 vec0 = tcu::randomVec4(rnd);
430 const tcu::Vec4 vec1 = tcu::randomVec4(rnd);
431 const tcu::Vec4 vec2 = tcu::randomVec4(rnd);
432 const tcu::Vec4 vec3 = tcu::randomVec4(rnd);
434 ValidationData data =
436 { vec0, vec1, vec2, vec3 },
437 { refValue, refValue, refValue, refValue }
439 copyRandomTests->addChild(new CopyImageTestCase(testCtx, name.c_str(), clearValue.color, data, cmdBufferType));
442 std::string groupName = getCmdBufferTypeStr(cmdBufferType);
443 std::string groupDesc = "Copy Image Tests with " + groupName + " command buffer";
444 de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
445 copyTests->addChild(copyStaticTests.release());
446 copyTests->addChild(copyRandomTests.release());
447 return copyTests.release();
452 tcu::TestCaseGroup* createCopyImageTests (tcu::TestContext& testCtx)
454 de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, "copy", "Copy Image Tests"));
456 copyTests->addChild(createCopyImageTests(testCtx, CMD_BUFFER_PRIMARY));
457 copyTests->addChild(createCopyImageTests(testCtx, CMD_BUFFER_SECONDARY));
459 return copyTests.release();