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 copy image to buffer tests 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktProtectedMemCopyImageToBufferTests.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 "vktProtectedMemBufferValidator.hpp" 41 42 namespace vkt 43 { 44 namespace ProtectedMem 45 { 46 47 namespace 48 { 49 50 enum { 51 BUFFER_SIZE = 256, 52 RENDER_WIDTH = 8, 53 RENDER_HEIGHT = 8, 54 55 MAX_POSITION = BUFFER_SIZE / 4, 56 }; 57 58 template<typename T> 59 class CopyImageToBufferTestInstance : public ProtectedTestInstance 60 { 61 public: 62 CopyImageToBufferTestInstance (Context& ctx, 63 const vk::VkClearColorValue fillValue, 64 const BufferValidator<T>& validator, 65 const CmdBufferType cmdBufferType); 66 virtual tcu::TestStatus iterate (void); 67 68 private: 69 const vk::VkFormat m_imageFormat; 70 const vk::VkClearColorValue m_fillValue; 71 const BufferValidator<T>& m_validator; 72 const CmdBufferType m_cmdBufferType; 73 }; 74 75 76 template<typename T> 77 class CopyImageToBufferTestCase : public TestCase 78 { 79 public: 80 CopyImageToBufferTestCase (tcu::TestContext& testCtx, 81 const std::string& name, 82 vk::VkClearColorValue fillValue, 83 ValidationData<T> data, 84 CmdBufferType cmdBufferType) 85 : TestCase (testCtx, name, "Copy image to buffer.") 86 , m_fillValue (fillValue) 87 , m_validator (data) 88 , m_cmdBufferType (cmdBufferType) 89 { 90 } 91 92 virtual ~CopyImageToBufferTestCase (void) {} 93 virtual TestInstance* createInstance (Context& ctx) const 94 { 95 return new CopyImageToBufferTestInstance<T>(ctx, m_fillValue, m_validator, m_cmdBufferType); 96 } 97 virtual void initPrograms (vk::SourceCollections& programCollection) const 98 { 99 m_validator.initPrograms(programCollection); 100 } 101 private: 102 vk::VkClearColorValue m_fillValue; 103 BufferValidator<T> m_validator; 104 CmdBufferType m_cmdBufferType; 105 }; 106 107 template<typename T> 108 CopyImageToBufferTestInstance<T>::CopyImageToBufferTestInstance (Context& ctx, 109 const vk::VkClearColorValue fillValue, 110 const BufferValidator<T>& validator, 111 const CmdBufferType cmdBufferType) 112 : ProtectedTestInstance (ctx) 113 , m_imageFormat (vk::VK_FORMAT_R32G32B32A32_UINT) 114 , m_fillValue (fillValue) 115 , m_validator (validator) 116 , m_cmdBufferType (cmdBufferType) 117 { 118 } 119 120 template<typename T> 121 tcu::TestStatus CopyImageToBufferTestInstance<T>::iterate() 122 { 123 ProtectedContext& ctx (m_protectedContext); 124 const vk::DeviceInterface& vk = ctx.getDeviceInterface(); 125 const vk::VkDevice device = ctx.getDevice(); 126 const vk::VkQueue queue = ctx.getQueue(); 127 const deUint32 queueFamilyIndex = ctx.getQueueFamilyIndex(); 128 129 // Create image 130 de::MovePtr<vk::ImageWithMemory> colorImage = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex, 131 RENDER_WIDTH, RENDER_HEIGHT, 132 m_imageFormat, 133 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT 134 | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT 135 | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT); 136 de::MovePtr<vk::BufferWithMemory> dstBuffer (makeBuffer(ctx, 137 PROTECTION_ENABLED, 138 queueFamilyIndex, 139 (deUint32)(BUFFER_SIZE * sizeof(deUint32)), 140 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT 141 | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, 142 vk::MemoryRequirement::Protected)); 143 144 vk::Unique<vk::VkCommandPool> cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex)); 145 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 146 vk::Unique<vk::VkCommandBuffer> secondaryCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY)); 147 vk::VkCommandBuffer targetCmdBuffer = (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer; 148 149 // Begin cmd buffer 150 beginCommandBuffer(vk, *cmdBuffer); 151 152 if (m_cmdBufferType == CMD_BUFFER_SECONDARY) 153 { 154 // Begin secondary command buffer 155 const vk::VkCommandBufferInheritanceInfo secCmdBufInheritInfo = 156 { 157 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 158 DE_NULL, 159 (vk::VkRenderPass)0u, // renderPass 160 0u, // subpass 161 (vk::VkFramebuffer)0u, // framebuffer 162 VK_FALSE, // occlusionQueryEnable 163 (vk::VkQueryControlFlags)0u, // queryFlags 164 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics 165 }; 166 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, secCmdBufInheritInfo); 167 } 168 169 // Start image barrier for source image. 170 { 171 const vk::VkImageMemoryBarrier startImgBarrier = 172 { 173 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType 174 DE_NULL, // const void* pNext 175 0, // VkAccessFlags srcAccessMask 176 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask 177 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout 178 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout 179 queueFamilyIndex, // uint32_t srcQueueFamilyIndex 180 queueFamilyIndex, // uint32_t dstQueueFamilyIndex 181 **colorImage, // VkImage image 182 { 183 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask 184 0u, // uint32_t baseMipLevel 185 1u, // uint32_t mipLevels 186 0u, // uint32_t baseArraySlice 187 1u, // uint32_t subresourceRange 188 } 189 }; 190 191 vk.cmdPipelineBarrier(targetCmdBuffer, 192 vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 193 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 194 (vk::VkDependencyFlags)0, 195 0, (const vk::VkMemoryBarrier*)DE_NULL, 196 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 197 1, &startImgBarrier); 198 } 199 200 // Image clear 201 const vk::VkImageSubresourceRange subresourceRange = 202 { 203 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask 204 0u, // uint32_t baseMipLevel 205 1u, // uint32_t levelCount 206 0u, // uint32_t baseArrayLayer 207 1u, // uint32_t layerCount 208 }; 209 210 vk.cmdClearColorImage(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_GENERAL, &m_fillValue, 1, &subresourceRange); 211 212 // Image barrier to change accessMask to transfer read bit for source image. 213 { 214 const vk::VkImageMemoryBarrier initializeBarrier = 215 { 216 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType 217 DE_NULL, // const void* pNext 218 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask 219 vk::VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask 220 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout 221 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout 222 queueFamilyIndex, // uint32_t srcQueueFamilyIndex 223 queueFamilyIndex, // uint32_t dstQueueFamilyIndex 224 **colorImage, // VkImage image 225 { 226 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask 227 0u, // uint32_t baseMipLevel 228 1u, // uint32_t mipLevels 229 0u, // uint32_t baseArraySlice 230 1u, // uint32_t subresourceRange 231 } 232 }; 233 234 vk.cmdPipelineBarrier(targetCmdBuffer, 235 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 236 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 237 (vk::VkDependencyFlags)0, 238 0, (const vk::VkMemoryBarrier*)DE_NULL, 239 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 240 1, &initializeBarrier); 241 } 242 243 // Copy image to buffer 244 const vk::VkImageSubresourceLayers subresourceLayers = 245 { 246 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask 247 0u, // uint32_t mipLevel 248 0u, // uint32_t baseArrayLayer 249 1u, // uint32_t layerCount 250 }; 251 const vk::VkOffset3D nullOffset = {0u, 0u, 0u}; 252 const vk::VkExtent3D imageExtent = {(deUint32)RENDER_WIDTH, (deUint32)RENDER_HEIGHT, 1u}; 253 const vk::VkBufferImageCopy copyRegion = 254 { 255 0ull, // VkDeviceSize srcOffset; 256 0, // uint32_t bufferRowLength 257 0, // uint32_t bufferImageHeight 258 subresourceLayers, // VkImageSubresourceLayers imageSubresource 259 nullOffset, // VkOffset3D imageOffset 260 imageExtent, // VkExtent3D imageExtent 261 }; 262 vk.cmdCopyImageToBuffer(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **dstBuffer, 1u, ©Region); 263 264 { 265 // Buffer validator reads buffer in compute shader 266 const vk::VkBufferMemoryBarrier endBufferBarrier = 267 { 268 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType 269 DE_NULL, // const void* pNext 270 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask 271 vk::VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask 272 queueFamilyIndex, // uint32_t srcQueueFamilyIndex 273 queueFamilyIndex, // uint32_t dstQueueFamilyIndex 274 **dstBuffer, // VkBuffer buffer 275 0u, // VkDeviceSize offset 276 VK_WHOLE_SIZE, // VkDeviceSize size 277 }; 278 vk.cmdPipelineBarrier(targetCmdBuffer, 279 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 280 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 281 (vk::VkDependencyFlags)0, 282 0, (const vk::VkMemoryBarrier*)DE_NULL, 283 1, &endBufferBarrier, 284 0, (const vk::VkImageMemoryBarrier*)DE_NULL); 285 } 286 287 if (m_cmdBufferType == CMD_BUFFER_SECONDARY) 288 { 289 endCommandBuffer(vk, *secondaryCmdBuffer); 290 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get()); 291 } 292 293 endCommandBuffer(vk, *cmdBuffer); 294 295 // Submit command buffer 296 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device)); 297 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull)); 298 299 // Log out test data 300 ctx.getTestContext().getLog() 301 << tcu::TestLog::Message << "Fill value: " << m_fillValue << tcu::TestLog::EndMessage; 302 303 // Validate resulting buffer 304 if (m_validator.validateBuffer(ctx, **dstBuffer)) 305 return tcu::TestStatus::pass("Everything went OK"); 306 else 307 return tcu::TestStatus::fail("Something went really wrong"); 308 } 309 310 tcu::TestCaseGroup* createCopyImageToFloatBufferTests(tcu::TestContext& testCtx, CmdBufferType cmdBufferType) 311 { 312 struct { 313 const vk::VkClearColorValue fillValue; 314 const ValidationDataVec4 data; 315 } testData[] = { 316 { { { 0.0f, 0.0f, 0.0f, 0.0f } }, 317 { 318 { tcu::IVec4(0), tcu::IVec4(1), tcu::IVec4(3), tcu::IVec4(7) }, 319 { tcu::Vec4(0.0f), tcu::Vec4(0.0f), tcu::Vec4(0.0f), tcu::Vec4(0.0f) } 320 } 321 }, 322 { { { 1.0f, 1.0f, 1.0f, 1.0f } }, 323 { 324 { tcu::IVec4(2), tcu::IVec4(4), tcu::IVec4(16), tcu::IVec4(15) }, 325 { tcu::Vec4(1.0f), tcu::Vec4(1.0f), tcu::Vec4(1.0f), tcu::Vec4(1.0f) } 326 } 327 }, 328 { { { 0.24f, 0.24f, 0.24f, 0.24f } }, 329 { 330 { tcu::IVec4(3), tcu::IVec4(7), tcu::IVec4(17), tcu::IVec4(37) }, 331 { tcu::Vec4(0.24f), tcu::Vec4(0.24f), tcu::Vec4(0.24f), tcu::Vec4(0.24f) } 332 } 333 }, 334 { { { 0.68f, 0.68f, 0.68f, 0.68f } }, 335 { 336 { tcu::IVec4(7), tcu::IVec4(11), tcu::IVec4(21), tcu::IVec4(40) }, 337 { tcu::Vec4(0.68f), tcu::Vec4(0.68f), tcu::Vec4(0.68f), tcu::Vec4(0.68f) } 338 } 339 }, 340 { { { 0.92f, 0.92f, 0.92f, 0.92f } }, 341 { 342 { tcu::IVec4(5), tcu::IVec4(21), tcu::IVec4(40), tcu::IVec4(57) }, 343 { tcu::Vec4(0.92f), tcu::Vec4(0.92f), tcu::Vec4(0.92f), tcu::Vec4(0.92f) } 344 } 345 }, 346 { { { 0.49f, 0.49f, 0.49f, 0.49f } }, 347 { 348 { tcu::IVec4(23), tcu::IVec4(37), tcu::IVec4(51), tcu::IVec4(63) }, 349 { tcu::Vec4(0.49f), tcu::Vec4(0.49f), tcu::Vec4(0.49f), tcu::Vec4(0.49f) } 350 } 351 }, 352 }; 353 354 de::MovePtr<tcu::TestCaseGroup> copyStaticTests (new tcu::TestCaseGroup(testCtx, "static", "Copy Image to Buffer Tests with static input")); 355 356 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx) 357 { 358 DE_ASSERT(testData[ndx].data.positions[0].x() < MAX_POSITION); 359 DE_ASSERT(testData[ndx].data.positions[1].x() < MAX_POSITION); 360 DE_ASSERT(testData[ndx].data.positions[2].x() < MAX_POSITION); 361 DE_ASSERT(testData[ndx].data.positions[3].x() < MAX_POSITION); 362 363 const std::string name = "copy_" + de::toString(ndx + 1); 364 copyStaticTests->addChild(new CopyImageToBufferTestCase<tcu::Vec4>(testCtx, name.c_str(), testData[ndx].fillValue, testData[ndx].data, cmdBufferType)); 365 } 366 367 /* Add a few randomized tests */ 368 de::MovePtr<tcu::TestCaseGroup> copyRandomTests (new tcu::TestCaseGroup(testCtx, "random", "Copy Image to Buffer Tests with random input")); 369 const int testCount = 10; 370 de::Random rnd (testCtx.getCommandLine().getBaseSeed()); 371 for (int ndx = 0; ndx < testCount; ++ndx) 372 { 373 const std::string name = "copy_" + de::toString(ndx + 1); 374 vk::VkClearValue clearValue = vk::makeClearValueColorF32( 375 rnd.getFloat(0.0, 1.0f), 376 rnd.getFloat(0.0, 1.0f), 377 rnd.getFloat(0.0, 1.0f), 378 rnd.getFloat(0.0, 1.0f)); 379 380 tcu::Vec4 refValue (clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]); 381 ValidationDataVec4 data = 382 { 383 { tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1)), 384 tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1)), 385 tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1)), 386 tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1)) }, 387 { refValue, refValue, refValue, refValue } 388 }; 389 390 DE_ASSERT(data.positions[0].x() < MAX_POSITION); 391 DE_ASSERT(data.positions[1].x() < MAX_POSITION); 392 DE_ASSERT(data.positions[2].x() < MAX_POSITION); 393 DE_ASSERT(data.positions[3].x() < MAX_POSITION); 394 395 copyRandomTests->addChild(new CopyImageToBufferTestCase<tcu::Vec4>(testCtx, name.c_str(), clearValue.color, data, cmdBufferType)); 396 } 397 398 std::string groupName = getCmdBufferTypeStr(cmdBufferType); 399 std::string groupDesc = "Copy Image to Buffer Tests with " + groupName + " command buffer"; 400 de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str())); 401 copyTests->addChild(copyStaticTests.release()); 402 copyTests->addChild(copyRandomTests.release()); 403 return copyTests.release(); 404 } 405 406 } // anonymous 407 408 tcu::TestCaseGroup* createCopyImageToFloatBufferTests (tcu::TestContext& testCtx) 409 { 410 de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, "copy_image_to_float_buffer", "Copy Image to Buffer Tests")); 411 412 copyTests->addChild(createCopyImageToFloatBufferTests(testCtx, CMD_BUFFER_PRIMARY)); 413 copyTests->addChild(createCopyImageToFloatBufferTests(testCtx, CMD_BUFFER_SECONDARY)); 414 415 return copyTests.release(); 416 } 417 418 } // ProtectedMem 419 } // vkt 420