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