1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * Copyright (c) 2016 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 Vulkan Fill Buffer Tests 23 *//*--------------------------------------------------------------------*/ 24 25#include "vktApiFillBufferTests.hpp" 26#include "vktApiBufferAndImageAllocationUtil.hpp" 27#include "vktCustomInstancesDevices.hpp" 28 29#include "deStringUtil.hpp" 30#include "deUniquePtr.hpp" 31#include "vkImageUtil.hpp" 32#include "vkMemUtil.hpp" 33#include "vkCmdUtil.hpp" 34#include "vktTestCase.hpp" 35#include "vktTestCaseUtil.hpp" 36#include "vkQueryUtil.hpp" 37#include "vkRefUtil.hpp" 38#include "vkCmdUtil.hpp" 39#include "vkSafetyCriticalUtil.hpp" 40#include "tcuImageCompare.hpp" 41#include "tcuCommandLine.hpp" 42#include "tcuTexture.hpp" 43#include "tcuTextureUtil.hpp" 44#include "tcuVectorType.hpp" 45#include "deSharedPtr.hpp" 46#include <limits> 47 48namespace vkt 49{ 50 51namespace api 52{ 53 54using namespace vk; 55 56namespace 57{ 58 59struct TestParams 60{ 61 enum 62 { 63 TEST_DATA_SIZE = 256 64 }; 65 66 VkDeviceSize dstSize; 67 VkDeviceSize dstOffset; 68 VkDeviceSize size; 69 deUint32 testData[TEST_DATA_SIZE]; 70 de::SharedPtr<IBufferAllocator> bufferAllocator; 71 bool useTransferOnlyQueue; 72}; 73 74// Creates a device that has transfer only operations 75Move<VkDevice> createCustomDevice(Context& context, uint32_t& queueFamilyIndex) 76{ 77 const InstanceInterface& instanceDriver = context.getInstanceInterface(); 78 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 79 80 queueFamilyIndex = findQueueFamilyIndexWithCaps(instanceDriver, physicalDevice, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT); 81 82 const std::vector<VkQueueFamilyProperties> queueFamilies = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice); 83 84 // This must be found, findQueueFamilyIndexWithCaps would have 85 // thrown a NotSupported exception if the requested queue type did 86 // not exist. Similarly, this was written with the assumption the 87 // "alternative" queue would be different to the universal queue. 88 DE_ASSERT(queueFamilyIndex < queueFamilies.size() && queueFamilyIndex != context.getUniversalQueueFamilyIndex()); 89 const float queuePriority = 1.0f; 90 const VkDeviceQueueCreateInfo deviceQueueCreateInfos 91 { 92 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType; 93 nullptr, // const void* pNext; 94 (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags; 95 queueFamilyIndex, // uint32_t queueFamilyIndex; 96 1u, // uint32_t queueCount; 97 &queuePriority, // const float* pQueuePriorities; 98 }; 99 100 // Replicate default device extension list. 101 const auto extensionNames = context.getDeviceCreationExtensions(); 102 auto synchronization2Features = context.getSynchronization2Features(); 103 auto deviceFeatures2 = context.getDeviceFeatures2(); 104 const void* pNext = &deviceFeatures2; 105 106 if (context.isDeviceFunctionalitySupported("VK_KHR_synchronization2")) 107 { 108 synchronization2Features.pNext = &deviceFeatures2; 109 pNext = &synchronization2Features; 110 } 111 112#ifdef CTS_USES_VULKANSC 113 VkDeviceObjectReservationCreateInfo memReservationInfo = context.getTestContext().getCommandLine().isSubProcess() ? context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo(); 114 memReservationInfo.pNext = pNext; 115 pNext = &memReservationInfo; 116 117 VkPipelineCacheCreateInfo pcCI; 118 std::vector<VkPipelinePoolSize> poolSizes; 119 if (context.getTestContext().getCommandLine().isSubProcess()) 120 { 121 if (context.getResourceInterface()->getCacheDataSize() > 0) 122 { 123 pcCI = 124 { 125 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType; 126 DE_NULL, // const void* pNext; 127 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT | 128 VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags; 129 context.getResourceInterface()->getCacheDataSize(), // deUintptr initialDataSize; 130 context.getResourceInterface()->getCacheData() // const void* pInitialData; 131 }; 132 memReservationInfo.pipelineCacheCreateInfoCount = 1; 133 memReservationInfo.pPipelineCacheCreateInfos = &pcCI; 134 } 135 poolSizes = context.getResourceInterface()->getPipelinePoolSizes(); 136 if (!poolSizes.empty()) 137 { 138 memReservationInfo.pipelinePoolSizeCount = deUint32(poolSizes.size()); 139 memReservationInfo.pPipelinePoolSizes = poolSizes.data(); 140 } 141 } 142#endif // CTS_USES_VULKANSC 143 144 const VkDeviceCreateInfo deviceCreateInfo 145 { 146 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType; 147 pNext, // const void* pNext; 148 (VkDeviceCreateFlags)0u, // VkDeviceCreateFlags flags; 149 1u, // uint32_t queueCreateInfoCount; 150 &deviceQueueCreateInfos, // const VkDeviceQueueCreateInfo* pQueueCreateInfos; 151 0u, // uint32_t enabledLayerCount; 152 DE_NULL, // const char* const* ppEnabledLayerNames; 153 static_cast<uint32_t>(extensionNames.size()), // uint32_t enabledExtensionCount; 154 extensionNames.data(), // const char* const* ppEnabledExtensionNames; 155 DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures; 156 }; 157 158 return vkt::createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), context.getInstance(), instanceDriver, physicalDevice, &deviceCreateInfo); 159} 160 161class FillWholeBufferTestInstance : public vkt::TestInstance 162{ 163public: 164 FillWholeBufferTestInstance (Context& context, const TestParams& testParams); 165 virtual tcu::TestStatus iterate (void) override; 166protected: 167 // dstSize will be used as the buffer size. 168 // dstOffset will be used as the offset for vkCmdFillBuffer. 169 // size in vkCmdFillBuffer will always be VK_WHOLE_SIZE. 170 const TestParams m_params; 171 172 Move<VkDevice> m_customDevice; 173 de::MovePtr<Allocator> m_customAllocator; 174 175 VkDevice m_device; 176 Allocator* m_allocator; 177 uint32_t m_queueFamilyIndex; 178 179 Move<VkCommandPool> m_cmdPool; 180 Move<VkCommandBuffer> m_cmdBuffer; 181 182 Move<VkBuffer> m_destination; 183 de::MovePtr<Allocation> m_destinationBufferAlloc; 184}; 185 186FillWholeBufferTestInstance::FillWholeBufferTestInstance(Context& context, const TestParams& testParams) 187 : vkt::TestInstance(context), m_params(testParams) 188{ 189 const InstanceInterface& vki = m_context.getInstanceInterface(); 190 const DeviceInterface& vk = m_context.getDeviceInterface(); 191 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice(); 192 193 if (testParams.useTransferOnlyQueue) 194 { 195 m_customDevice = createCustomDevice(context, m_queueFamilyIndex); 196 m_customAllocator = de::MovePtr<Allocator>(new SimpleAllocator(vk, *m_customDevice, getPhysicalDeviceMemoryProperties(vki, physDevice))); 197 198 m_device = *m_customDevice; 199 m_allocator = &(*m_customAllocator); 200 } 201 else 202 { 203 m_device = context.getDevice(); 204 m_allocator = &context.getDefaultAllocator(); 205 m_queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 206 } 207 208 m_cmdPool = createCommandPool(vk, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex); 209 m_cmdBuffer = allocateCommandBuffer(vk, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 210 testParams.bufferAllocator->createTestBuffer(vk, m_device, m_queueFamilyIndex, m_params.dstSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, context, *m_allocator, m_destination, MemoryRequirement::HostVisible, m_destinationBufferAlloc); 211} 212 213tcu::TestStatus FillWholeBufferTestInstance::iterate(void) 214{ 215 const DeviceInterface& vk = m_context.getDeviceInterface(); 216 const VkQueue queue = getDeviceQueue(vk, m_device, m_queueFamilyIndex, 0); 217 218 // if posible use synchronization2 when testing transfer only queue 219 const bool useSynchronization2 = m_context.isDeviceFunctionalitySupported("VK_KHR_synchronization2") && m_params.useTransferOnlyQueue; 220 221 // Make sure some stuff below will work. 222 DE_ASSERT(m_params.dstSize >= sizeof(deUint32)); 223 DE_ASSERT(m_params.dstSize < static_cast<VkDeviceSize>(std::numeric_limits<size_t>::max())); 224 DE_ASSERT(m_params.dstOffset < m_params.dstSize); 225 226 // Fill buffer from the host and flush buffer memory. 227 deUint8* bytes = reinterpret_cast<deUint8*>(m_destinationBufferAlloc->getHostPtr()); 228 deMemset(bytes, 0xff, static_cast<size_t>(m_params.dstSize)); 229 flushAlloc(vk, m_device, *m_destinationBufferAlloc); 230 231 const VkBufferMemoryBarrier gpuToHostBarrier 232 { 233 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 234 DE_NULL, // const void* pNext; 235 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 236 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 237 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 238 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 239 *m_destination, // VkBuffer buffer; 240 0u, // VkDeviceSize offset; 241 VK_WHOLE_SIZE // VkDeviceSize size; 242 }; 243 244#ifndef CTS_USES_VULKANSC 245 using BufferMemoryBarrier2 = VkBufferMemoryBarrier2; 246 using DependencyInfo = VkDependencyInfo; 247 using CommandBufferSubmitInfo = VkCommandBufferSubmitInfo; 248 using SubmitInfo2 = VkSubmitInfo2; 249 auto cmdPipelineBarrier2Fun = &DeviceInterface::cmdPipelineBarrier2; 250 auto queueSubmit2Fun = &DeviceInterface::queueSubmit2; 251#else 252 using BufferMemoryBarrier2 = VkBufferMemoryBarrier2KHR; 253 using DependencyInfo = VkDependencyInfoKHR; 254 using CommandBufferSubmitInfo = VkCommandBufferSubmitInfoKHR; 255 using SubmitInfo2 = VkSubmitInfo2KHR; 256 auto cmdPipelineBarrier2Fun = &DeviceInterface::cmdPipelineBarrier2KHR; 257 auto queueSubmit2Fun = &DeviceInterface::queueSubmit2KHR; 258#endif // CTS_USES_VULKANSC 259 260 BufferMemoryBarrier2 gpuToHostBarrier2 = initVulkanStructure(); 261 gpuToHostBarrier2.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR; 262 gpuToHostBarrier2.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR; 263 gpuToHostBarrier2.dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT_KHR; 264 gpuToHostBarrier2.dstAccessMask = VK_ACCESS_2_HOST_READ_BIT_KHR; 265 gpuToHostBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 266 gpuToHostBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 267 gpuToHostBarrier2.buffer = *m_destination; 268 gpuToHostBarrier2.size = VK_WHOLE_SIZE; 269 270 DependencyInfo depInfo = initVulkanStructure(); 271 depInfo.bufferMemoryBarrierCount = 1; 272 depInfo.pBufferMemoryBarriers = &gpuToHostBarrier2; 273 274 // Fill buffer using VK_WHOLE_SIZE. 275 beginCommandBuffer(vk, *m_cmdBuffer); 276 vk.cmdFillBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, VK_WHOLE_SIZE, deUint32{0x01010101}); 277 278 if (useSynchronization2) 279 (vk.*(cmdPipelineBarrier2Fun))(*m_cmdBuffer, &depInfo); 280 else 281 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, DE_NULL, 1, &gpuToHostBarrier, 0, DE_NULL); 282 283 endCommandBuffer(vk, *m_cmdBuffer); 284 285 Move<VkFence> fence(createFence(vk, m_device)); 286 if (useSynchronization2) 287 { 288 CommandBufferSubmitInfo commandBufferInfos = initVulkanStructure(); 289 commandBufferInfos.commandBuffer = *m_cmdBuffer; 290 291 SubmitInfo2 submitInfo2 = initVulkanStructure(); 292 submitInfo2.commandBufferInfoCount = 1u; 293 submitInfo2.pCommandBufferInfos = &commandBufferInfos; 294 295 (vk.*(queueSubmit2Fun))(queue, 1u, &submitInfo2, *fence); 296 } 297 else 298 { 299 VkSubmitInfo submitInfo = initVulkanStructure(); 300 submitInfo.commandBufferCount = 1u; 301 submitInfo.pCommandBuffers = &m_cmdBuffer.get(); 302 303 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); 304 } 305 waitForFence(vk, m_device, *fence); 306 307 // Invalidate buffer memory and check the buffer contains the expected results. 308 invalidateAlloc(vk, m_device, *m_destinationBufferAlloc); 309 310 const VkDeviceSize startOfExtra = (m_params.dstSize / sizeof(deUint32)) * sizeof(deUint32); 311 for (VkDeviceSize i = 0; i < m_params.dstSize; ++i) 312 { 313 const deUint8 expectedByte = ((i >= m_params.dstOffset && i < startOfExtra)? 0x01 : 0xff); 314 if (bytes[i] != expectedByte) 315 { 316 std::ostringstream msg; 317 msg << "Invalid byte at position " << i << " in the buffer (found 0x" 318 << std::hex << static_cast<int>(bytes[i]) << " but expected 0x" << static_cast<int>(expectedByte) << ")"; 319 return tcu::TestStatus::fail(msg.str()); 320 } 321 } 322 323 return tcu::TestStatus::pass("Pass"); 324} 325 326class FillWholeBufferTestCase : public vkt::TestCase 327{ 328public: 329 FillWholeBufferTestCase (tcu::TestContext& testCtx, 330 const std::string& name, 331 const TestParams params) 332 : vkt::TestCase(testCtx, name), m_params(params) 333 {} 334 335 virtual TestInstance* createInstance (Context& context) const override 336 { 337 return static_cast<TestInstance*>(new FillWholeBufferTestInstance(context, m_params)); 338 } 339private: 340 const TestParams m_params; 341}; 342 343 344class FillBufferTestInstance : public vkt::TestInstance 345{ 346public: 347 FillBufferTestInstance (Context& context, 348 TestParams testParams); 349 virtual tcu::TestStatus iterate (void); 350protected: 351 const TestParams m_params; 352 353 Move<VkDevice> m_customDevice; 354 de::MovePtr<Allocator> m_customAllocator; 355 356 VkDevice m_device; 357 Allocator* m_allocator; 358 uint32_t m_queueFamilyIndex; 359 360 Move<VkCommandPool> m_cmdPool; 361 Move<VkCommandBuffer> m_cmdBuffer; 362 de::MovePtr<tcu::TextureLevel> m_destinationTextureLevel; 363 de::MovePtr<tcu::TextureLevel> m_expectedTextureLevel; 364 365 VkCommandBufferBeginInfo m_cmdBufferBeginInfo; 366 367 Move<VkBuffer> m_destination; 368 de::MovePtr<Allocation> m_destinationBufferAlloc; 369 370 void generateBuffer (tcu::PixelBufferAccess buffer, 371 int width, 372 int height, 373 int depth = 1); 374 virtual void generateExpectedResult (void); 375 void uploadBuffer (tcu::ConstPixelBufferAccess 376 bufferAccess, 377 const Allocation& bufferAlloc); 378 virtual tcu::TestStatus checkTestResult (tcu::ConstPixelBufferAccess 379 result); 380 deUint32 calculateSize (tcu::ConstPixelBufferAccess 381 src) const 382 { 383 return src.getWidth() * src.getHeight() * src.getDepth() * tcu::getPixelSize(src.getFormat()); 384 } 385}; 386 387 FillBufferTestInstance::FillBufferTestInstance 388 (Context& context, 389 TestParams testParams) 390 : vkt::TestInstance (context) 391 , m_params (testParams) 392{ 393 const InstanceInterface& vki = m_context.getInstanceInterface(); 394 const DeviceInterface& vk = m_context.getDeviceInterface(); 395 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice(); 396 397 if (testParams.useTransferOnlyQueue) 398 { 399 m_customDevice = createCustomDevice(context, m_queueFamilyIndex); 400 m_customAllocator = de::MovePtr<Allocator>(new SimpleAllocator(vk, *m_customDevice, getPhysicalDeviceMemoryProperties(vki, physDevice))); 401 402 m_device = *m_customDevice; 403 m_allocator = &(*m_customAllocator); 404 } 405 else 406 { 407 m_device = context.getDevice(); 408 m_allocator = &context.getDefaultAllocator(); 409 m_queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 410 } 411 412 // Create command pool 413 m_cmdPool = createCommandPool(vk, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex); 414 415 // Create command buffer 416 m_cmdBuffer = allocateCommandBuffer(vk, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 417 418 testParams.bufferAllocator->createTestBuffer(vk, m_device, m_queueFamilyIndex, m_params.dstSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, context, *m_allocator, m_destination, MemoryRequirement::HostVisible, m_destinationBufferAlloc); 419} 420 421tcu::TestStatus FillBufferTestInstance::iterate (void) 422{ 423 const int dstLevelWidth = (int)(m_params.dstSize / 4); 424 m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), dstLevelWidth, 1)); 425 426 generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1); 427 428 generateExpectedResult(); 429 430 uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc); 431 432 const DeviceInterface& vk = m_context.getDeviceInterface(); 433 const VkQueue queue = getDeviceQueue(vk, m_device, m_queueFamilyIndex, 0); 434 435 const VkBufferMemoryBarrier dstBufferBarrier = 436 { 437 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 438 DE_NULL, // const void* pNext; 439 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 440 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 441 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 442 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 443 *m_destination, // VkBuffer buffer; 444 m_params.dstOffset, // VkDeviceSize offset; 445 VK_WHOLE_SIZE // VkDeviceSize size; 446 }; 447 448 beginCommandBuffer(vk, *m_cmdBuffer); 449 vk.cmdFillBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, m_params.size, m_params.testData[0]); 450 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); 451 endCommandBuffer(vk, *m_cmdBuffer); 452 453 submitCommandsAndWait(vk, m_device, queue, m_cmdBuffer.get()); 454 455 // Read buffer data 456 de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(m_destinationTextureLevel->getAccess().getFormat(), dstLevelWidth, 1)); 457 invalidateAlloc(vk, m_device, *m_destinationBufferAlloc); 458 tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr())); 459 460 return checkTestResult(resultLevel->getAccess()); 461} 462 463void FillBufferTestInstance::generateBuffer 464 (tcu::PixelBufferAccess buffer, 465 int width, 466 int height, 467 int depth) 468{ 469 for (int z = 0; z < depth; z++) 470 { 471 for (int y = 0; y < height; y++) 472 { 473 for (int x = 0; x < width; x++) 474 buffer.setPixel(tcu::UVec4(x, y, z, 255), x, y, z); 475 } 476 } 477} 478 479void FillBufferTestInstance::uploadBuffer 480 (tcu::ConstPixelBufferAccess 481 bufferAccess, 482 const Allocation& bufferAlloc) 483{ 484 const DeviceInterface& vk = m_context.getDeviceInterface(); 485 const deUint32 bufferSize = calculateSize(bufferAccess); 486 487 // Write buffer data 488 deMemcpy(bufferAlloc.getHostPtr(), bufferAccess.getDataPtr(), bufferSize); 489 flushAlloc(vk, m_device, bufferAlloc); 490} 491 492tcu::TestStatus FillBufferTestInstance::checkTestResult 493 (tcu::ConstPixelBufferAccess 494 result) 495{ 496 const tcu::ConstPixelBufferAccess 497 expected = m_expectedTextureLevel->getAccess(); 498 const tcu::UVec4 threshold (0, 0, 0, 0); 499 500 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparsion", expected, result, threshold, tcu::COMPARE_LOG_RESULT)) 501 { 502 return tcu::TestStatus::fail("Fill and Update Buffer test"); 503 } 504 505 return tcu::TestStatus::pass("Fill and Update Buffer test"); 506} 507 508void FillBufferTestInstance::generateExpectedResult 509 (void) 510{ 511 const tcu::ConstPixelBufferAccess 512 dst = m_destinationTextureLevel->getAccess(); 513 514 m_expectedTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth())); 515 tcu::copy(m_expectedTextureLevel->getAccess(), dst); 516 517 deUint32* currentPtr = (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4; 518 deUint32* endPtr = currentPtr + m_params.size / 4; 519 520 while (currentPtr < endPtr) 521 { 522 *currentPtr = m_params.testData[0]; 523 currentPtr++; 524 } 525} 526 527class FillBufferTestCase : public vkt::TestCase 528{ 529public: 530 FillBufferTestCase (tcu::TestContext& testCtx, 531 const std::string& name, 532 const TestParams params) 533 : vkt::TestCase (testCtx, name) 534 , m_params (params) 535 {} 536 537 virtual TestInstance* createInstance (Context& context) const 538 { 539 return static_cast<TestInstance*>(new FillBufferTestInstance(context, m_params)); 540 } 541private: 542 const TestParams m_params; 543}; 544 545// Update Buffer 546 547class UpdateBufferTestInstance : public FillBufferTestInstance 548{ 549public: 550 UpdateBufferTestInstance (Context& context, 551 TestParams testParams) 552 : FillBufferTestInstance (context, testParams) 553 {} 554 virtual tcu::TestStatus iterate (void); 555 556protected: 557 virtual void generateExpectedResult (void); 558}; 559 560tcu::TestStatus UpdateBufferTestInstance::iterate (void) 561{ 562 const int dstLevelWidth = (int)(m_params.dstSize / 4); 563 m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), dstLevelWidth, 1)); 564 565 generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1); 566 567 generateExpectedResult(); 568 569 uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc); 570 571 const DeviceInterface& vk = m_context.getDeviceInterface(); 572 const VkQueue queue = getDeviceQueue(vk, m_device, m_queueFamilyIndex, 0); 573 574 const VkBufferMemoryBarrier dstBufferBarrier = 575 { 576 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 577 DE_NULL, // const void* pNext; 578 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 579 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 580 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 581 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 582 *m_destination, // VkBuffer buffer; 583 m_params.dstOffset, // VkDeviceSize offset; 584 VK_WHOLE_SIZE // VkDeviceSize size; 585 }; 586 587 beginCommandBuffer(vk, *m_cmdBuffer); 588 vk.cmdUpdateBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, m_params.size, m_params.testData); 589 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); 590 endCommandBuffer(vk, *m_cmdBuffer); 591 592 submitCommandsAndWait(vk, m_device, queue, m_cmdBuffer.get()); 593 594 // Read buffer data 595 de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(m_destinationTextureLevel->getAccess().getFormat(), dstLevelWidth, 1)); 596 invalidateAlloc(vk, m_device, *m_destinationBufferAlloc); 597 tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr())); 598 599 return checkTestResult(resultLevel->getAccess()); 600} 601 602void UpdateBufferTestInstance::generateExpectedResult 603 (void) 604{ 605 const tcu::ConstPixelBufferAccess 606 dst = m_destinationTextureLevel->getAccess(); 607 608 m_expectedTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth())); 609 tcu::copy(m_expectedTextureLevel->getAccess(), dst); 610 611 deUint32* currentPtr = (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4; 612 613 deMemcpy(currentPtr, m_params.testData, (size_t)m_params.size); 614} 615 616class UpdateBufferTestCase : public vkt::TestCase 617{ 618public: 619 UpdateBufferTestCase (tcu::TestContext& testCtx, 620 const std::string& name, 621 const TestParams params) 622 : vkt::TestCase (testCtx, name) 623 , m_params (params) 624 {} 625 626 virtual TestInstance* createInstance (Context& context) const 627 { 628 return (TestInstance*) new UpdateBufferTestInstance(context, m_params); 629 } 630private: 631 TestParams m_params; 632}; 633 634} // anonymous 635 636tcu::TestCaseGroup* createFillAndUpdateBufferTests (tcu::TestContext& testCtx) 637{ 638 const de::SharedPtr<IBufferAllocator> bufferAllocators[] 639 { 640 de::SharedPtr<BufferSuballocation>(new BufferSuballocation()), 641 de::SharedPtr<BufferDedicatedAllocation>(new BufferDedicatedAllocation()) 642 }; 643 644 de::MovePtr<tcu::TestCaseGroup> fillAndUpdateBufferTests(new tcu::TestCaseGroup(testCtx, "fill_and_update_buffer")); 645 646 struct TestGroupData 647 { 648 const char* name; 649 bool useDedicatedAllocation; 650 bool useTransferOnlyQueue; 651 }; 652 const TestGroupData testGroupData[] 653 { 654 // BufferView Fill and Update Tests for Suballocated Objects 655 { "suballocation",false, false }, 656 // BufferView Fill and Update Tests for Suballocated Objects on transfer only queue 657 { "suballocation_transfer_queue",false, true }, 658 // BufferView Fill and Update Tests for Dedicatedly Allocated Objects 659 { "dedicated_alloc",true, false }, 660 }; 661 662 TestParams params; 663 for (const auto& groupData : testGroupData) 664 { 665 de::MovePtr<tcu::TestCaseGroup> currentTestsGroup(new tcu::TestCaseGroup(testCtx, groupData.name)); 666 667 params.dstSize = TestParams::TEST_DATA_SIZE; 668 params.bufferAllocator = bufferAllocators[groupData.useDedicatedAllocation]; 669 params.useTransferOnlyQueue = groupData.useTransferOnlyQueue; 670 671 deUint8* data = (deUint8*) params.testData; 672 for (deUint32 b = 0u; b < (params.dstSize * sizeof(params.testData[0])); b++) 673 data[b] = (deUint8) (b % 255); 674 675 { 676 const std::string testName ("buffer_whole"); 677 678 params.dstOffset = 0; 679 params.size = params.dstSize; 680 681 currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, params)); 682 currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, params)); 683 } 684 685 { 686 const std::string testName ("buffer_first_one"); 687 688 params.dstOffset = 0; 689 params.size = 4; 690 691 currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, params)); 692 currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, params)); 693 } 694 695 { 696 const std::string testName ("buffer_second_one"); 697 698 params.dstOffset = 4; 699 params.size = 4; 700 701 currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, params)); 702 currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, params)); 703 } 704 705 { 706 const std::string testName ("buffer_second_part"); 707 708 params.dstOffset = params.dstSize / 2; 709 params.size = params.dstSize / 2; 710 711 currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, params)); 712 currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, params)); 713 } 714 715 // VK_WHOLE_SIZE tests. 716 { 717 for (VkDeviceSize i = 0; i < sizeof(deUint32); ++i) 718 { 719 for (VkDeviceSize j = 0; j < sizeof(deUint32); ++j) 720 { 721 params.dstSize = TestParams::TEST_DATA_SIZE + i; 722 params.dstOffset = j * sizeof(deUint32); 723 params.size = VK_WHOLE_SIZE; 724 725 const VkDeviceSize extraBytes = params.dstSize % sizeof(deUint32); 726 const std::string name = "fill_buffer_vk_whole_size_" + de::toString(extraBytes) + "_extra_bytes_offset_" + de::toString(params.dstOffset); 727 728 currentTestsGroup->addChild(new FillWholeBufferTestCase{testCtx, name, params}); 729 } 730 } 731 } 732 733 fillAndUpdateBufferTests->addChild(currentTestsGroup.release()); 734 } 735 736 return fillAndUpdateBufferTests.release(); 737} 738 739} // api 740} // vkt 741