1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * Copyright (c) 2016 Imagination Technologies 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 Robustness Utilities 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktRobustnessUtil.hpp" 26 #include "vkDefs.hpp" 27 #include "vkImageUtil.hpp" 28 #include "vkPrograms.hpp" 29 #include "vkQueryUtil.hpp" 30 #include "vkRefUtil.hpp" 31 #include "vkTypeUtil.hpp" 32 #include "vkCmdUtil.hpp" 33 #include "vkObjUtil.hpp" 34 #include "deMath.h" 35 #include <iomanip> 36 #include <limits> 37 #include <sstream> 38 39 namespace vkt 40 { 41 namespace robustness 42 { 43 44 using namespace vk; 45 46 Move<VkDevice> createRobustBufferAccessDevice (Context& context) 47 { 48 const float queuePriority = 1.0f; 49 50 // Create a universal queue that supports graphics and compute 51 const VkDeviceQueueCreateInfo queueParams = 52 { 53 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType; 54 DE_NULL, // const void* pNext; 55 0u, // VkDeviceQueueCreateFlags flags; 56 context.getUniversalQueueFamilyIndex(), // deUint32 queueFamilyIndex; 57 1u, // deUint32 queueCount; 58 &queuePriority // const float* pQueuePriorities; 59 }; 60 61 VkPhysicalDeviceFeatures enabledFeatures = context.getDeviceFeatures(); 62 enabledFeatures.robustBufferAccess = true; 63 64 const VkDeviceCreateInfo deviceParams = 65 { 66 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType; 67 DE_NULL, // const void* pNext; 68 0u, // VkDeviceCreateFlags flags; 69 1u, // deUint32 queueCreateInfoCount; 70 &queueParams, // const VkDeviceQueueCreateInfo* pQueueCreateInfos; 71 0u, // deUint32 enabledLayerCount; 72 DE_NULL, // const char* const* ppEnabledLayerNames; 73 0u, // deUint32 enabledExtensionCount; 74 DE_NULL, // const char* const* ppEnabledExtensionNames; 75 &enabledFeatures // const VkPhysicalDeviceFeatures* pEnabledFeatures; 76 }; 77 78 return createDevice(context.getPlatformInterface(), context.getInstance(), 79 context.getInstanceInterface(), context.getPhysicalDevice(), &deviceParams); 80 } 81 82 bool areEqual (float a, float b) 83 { 84 return deFloatAbs(a - b) <= 0.001f; 85 } 86 87 bool isValueZero (const void* valuePtr, size_t valueSizeInBytes) 88 { 89 const deUint8* bytePtr = reinterpret_cast<const deUint8*>(valuePtr); 90 91 for (size_t i = 0; i < valueSizeInBytes; i++) 92 { 93 if (bytePtr[i] != 0) 94 return false; 95 } 96 97 return true; 98 } 99 100 bool isValueWithinBuffer (const void* buffer, VkDeviceSize bufferSize, const void* valuePtr, size_t valueSizeInBytes) 101 { 102 const deUint8* byteBuffer = reinterpret_cast<const deUint8*>(buffer); 103 104 if (bufferSize < ((VkDeviceSize)valueSizeInBytes)) 105 return false; 106 107 for (VkDeviceSize i = 0; i <= (bufferSize - valueSizeInBytes); i++) 108 { 109 if (!deMemCmp(&byteBuffer[i], valuePtr, valueSizeInBytes)) 110 return true; 111 } 112 113 return false; 114 } 115 116 bool isValueWithinBufferOrZero (const void* buffer, VkDeviceSize bufferSize, const void* valuePtr, size_t valueSizeInBytes) 117 { 118 return isValueWithinBuffer(buffer, bufferSize, valuePtr, valueSizeInBytes) || isValueZero(valuePtr, valueSizeInBytes); 119 } 120 121 bool verifyOutOfBoundsVec4 (const void* vecPtr, VkFormat bufferFormat) 122 { 123 if (isUintFormat(bufferFormat)) 124 { 125 const deUint32* data = (deUint32*)vecPtr; 126 127 return data[0] == 0u 128 && data[1] == 0u 129 && data[2] == 0u 130 && (data[3] == 0u || data[3] == 1u || data[3] == std::numeric_limits<deUint32>::max()); 131 } 132 else if (isIntFormat(bufferFormat)) 133 { 134 const deInt32* data = (deInt32*)vecPtr; 135 136 return data[0] == 0 137 && data[1] == 0 138 && data[2] == 0 139 && (data[3] == 0 || data[3] == 1 || data[3] == std::numeric_limits<deInt32>::max()); 140 } 141 else if (isFloatFormat(bufferFormat)) 142 { 143 const float* data = (float*)vecPtr; 144 145 return areEqual(data[0], 0.0f) 146 && areEqual(data[1], 0.0f) 147 && areEqual(data[2], 0.0f) 148 && (areEqual(data[3], 0.0f) || areEqual(data[3], 1.0f)); 149 } 150 else if (bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32) 151 { 152 return *((deUint32*)vecPtr) == 0xc0000000u; 153 } 154 155 DE_ASSERT(false); 156 return false; 157 } 158 159 void populateBufferWithTestValues (void* buffer, VkDeviceSize size, VkFormat format) 160 { 161 // Assign a sequence of 32-bit values 162 for (VkDeviceSize scalarNdx = 0; scalarNdx < size / 4; scalarNdx++) 163 { 164 const deUint32 valueIndex = (deUint32)(2 + scalarNdx); // Do not use 0 or 1 165 166 if (isUintFormat(format)) 167 { 168 reinterpret_cast<deUint32*>(buffer)[scalarNdx] = valueIndex; 169 } 170 else if (isIntFormat(format)) 171 { 172 reinterpret_cast<deInt32*>(buffer)[scalarNdx] = -deInt32(valueIndex); 173 } 174 else if (isFloatFormat(format)) 175 { 176 reinterpret_cast<float*>(buffer)[scalarNdx] = float(valueIndex); 177 } 178 else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) 179 { 180 const deUint32 r = ((valueIndex + 0) & ((2u << 10) - 1u)); 181 const deUint32 g = ((valueIndex + 1) & ((2u << 10) - 1u)); 182 const deUint32 b = ((valueIndex + 2) & ((2u << 10) - 1u)); 183 const deUint32 a = ((valueIndex + 0) & ((2u << 2) - 1u)); 184 185 reinterpret_cast<deUint32*>(buffer)[scalarNdx] = (a << 30) | (b << 20) | (g << 10) | r; 186 } 187 else 188 { 189 DE_ASSERT(false); 190 } 191 } 192 } 193 194 void logValue (std::ostringstream& logMsg, const void* valuePtr, VkFormat valueFormat, size_t valueSize) 195 { 196 if (isUintFormat(valueFormat)) 197 { 198 logMsg << *reinterpret_cast<const deUint32*>(valuePtr); 199 } 200 else if (isIntFormat(valueFormat)) 201 { 202 logMsg << *reinterpret_cast<const deInt32*>(valuePtr); 203 } 204 else if (isFloatFormat(valueFormat)) 205 { 206 logMsg << *reinterpret_cast<const float*>(valuePtr); 207 } 208 else 209 { 210 const deUint8* bytePtr = reinterpret_cast<const deUint8*>(valuePtr); 211 const std::ios::fmtflags streamFlags = logMsg.flags(); 212 213 logMsg << std::hex; 214 for (size_t i = 0; i < valueSize; i++) 215 { 216 logMsg << " " << (deUint32)bytePtr[i]; 217 } 218 logMsg.flags(streamFlags); 219 } 220 } 221 222 // TestEnvironment 223 224 TestEnvironment::TestEnvironment (Context& context, 225 VkDevice device, 226 VkDescriptorSetLayout descriptorSetLayout, 227 VkDescriptorSet descriptorSet) 228 : m_context (context) 229 , m_device (device) 230 , m_descriptorSetLayout (descriptorSetLayout) 231 , m_descriptorSet (descriptorSet) 232 { 233 const DeviceInterface& vk = context.getDeviceInterface(); 234 235 // Create command pool 236 { 237 const VkCommandPoolCreateInfo commandPoolParams = 238 { 239 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; 240 DE_NULL, // const void* pNext; 241 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags; 242 context.getUniversalQueueFamilyIndex() // deUint32 queueFamilyIndex; 243 }; 244 245 m_commandPool = createCommandPool(vk, m_device, &commandPoolParams); 246 } 247 248 // Create command buffer 249 { 250 const VkCommandBufferAllocateInfo commandBufferAllocateInfo = 251 { 252 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; 253 DE_NULL, // const void* pNext; 254 *m_commandPool, // VkCommandPool commandPool; 255 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; 256 1u, // deUint32 bufferCount; 257 }; 258 259 m_commandBuffer = allocateCommandBuffer(vk, m_device, &commandBufferAllocateInfo); 260 } 261 } 262 263 VkCommandBuffer TestEnvironment::getCommandBuffer (void) 264 { 265 return *m_commandBuffer; 266 } 267 268 // GraphicsEnvironment 269 270 GraphicsEnvironment::GraphicsEnvironment (Context& context, 271 VkDevice device, 272 VkDescriptorSetLayout descriptorSetLayout, 273 VkDescriptorSet descriptorSet, 274 const VertexBindings& vertexBindings, 275 const VertexAttributes& vertexAttributes, 276 const DrawConfig& drawConfig) 277 278 : TestEnvironment (context, device, descriptorSetLayout, descriptorSet) 279 , m_renderSize (16, 16) 280 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) 281 { 282 const DeviceInterface& vk = context.getDeviceInterface(); 283 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 284 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 285 SimpleAllocator memAlloc (vk, m_device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 286 287 // Create color image and view 288 { 289 const VkImageCreateInfo colorImageParams = 290 { 291 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 292 DE_NULL, // const void* pNext; 293 0u, // VkImageCreateFlags flags; 294 VK_IMAGE_TYPE_2D, // VkImageType imageType; 295 m_colorFormat, // VkFormat format; 296 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u }, // VkExtent3D extent; 297 1u, // deUint32 mipLevels; 298 1u, // deUint32 arrayLayers; 299 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 300 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 301 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 302 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 303 1u, // deUint32 queueFamilyIndexCount; 304 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 305 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 306 }; 307 308 m_colorImage = createImage(vk, m_device, &colorImageParams); 309 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, m_device, *m_colorImage), MemoryRequirement::Any); 310 VK_CHECK(vk.bindImageMemory(m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset())); 311 312 const VkImageViewCreateInfo colorAttachmentViewParams = 313 { 314 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 315 DE_NULL, // const void* pNext; 316 0u, // VkImageViewCreateFlags flags; 317 *m_colorImage, // VkImage image; 318 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 319 m_colorFormat, // VkFormat format; 320 componentMappingRGBA, // VkComponentMapping components; 321 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 322 }; 323 324 m_colorAttachmentView = createImageView(vk, m_device, &colorAttachmentViewParams); 325 } 326 327 // Create render pass 328 m_renderPass = makeRenderPass(vk, m_device, m_colorFormat); 329 330 // Create framebuffer 331 { 332 const VkFramebufferCreateInfo framebufferParams = 333 { 334 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 335 DE_NULL, // const void* pNext; 336 0u, // VkFramebufferCreateFlags flags; 337 *m_renderPass, // VkRenderPass renderPass; 338 1u, // deUint32 attachmentCount; 339 &m_colorAttachmentView.get(), // const VkImageView* pAttachments; 340 (deUint32)m_renderSize.x(), // deUint32 width; 341 (deUint32)m_renderSize.y(), // deUint32 height; 342 1u // deUint32 layers; 343 }; 344 345 m_framebuffer = createFramebuffer(vk, m_device, &framebufferParams); 346 } 347 348 // Create pipeline layout 349 { 350 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 351 { 352 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 353 DE_NULL, // const void* pNext; 354 0u, // VkPipelineLayoutCreateFlags flags; 355 1u, // deUint32 setLayoutCount; 356 &m_descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts; 357 0u, // deUint32 pushConstantRangeCount; 358 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 359 }; 360 361 m_pipelineLayout = createPipelineLayout(vk, m_device, &pipelineLayoutParams); 362 } 363 364 m_vertexShaderModule = createShaderModule(vk, m_device, m_context.getBinaryCollection().get("vertex"), 0); 365 m_fragmentShaderModule = createShaderModule(vk, m_device, m_context.getBinaryCollection().get("fragment"), 0); 366 367 // Create pipeline 368 { 369 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 370 { 371 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 372 DE_NULL, // const void* pNext; 373 0u, // VkPipelineVertexInputStateCreateFlags flags; 374 (deUint32)vertexBindings.size(), // deUint32 vertexBindingDescriptionCount; 375 vertexBindings.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 376 (deUint32)vertexAttributes.size(), // deUint32 vertexAttributeDescriptionCount; 377 vertexAttributes.data() // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 378 }; 379 380 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize)); 381 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize)); 382 383 m_graphicsPipeline = makeGraphicsPipeline(vk, // const DeviceInterface& vk 384 m_device, // const VkDevice device 385 *m_pipelineLayout, // const VkPipelineLayout pipelineLayout 386 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule 387 DE_NULL, // const VkShaderModule tessellationControlShaderModule 388 DE_NULL, // const VkShaderModule tessellationEvalShaderModule 389 DE_NULL, // const VkShaderModule geometryShaderModule 390 *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule 391 *m_renderPass, // const VkRenderPass renderPass 392 viewports, // const std::vector<VkViewport>& viewports 393 scissors, // const std::vector<VkRect2D>& scissors 394 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology topology 395 0u, // const deUint32 subpass 396 0u, // const deUint32 patchControlPoints 397 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo 398 } 399 400 // Record commands 401 { 402 const VkImageMemoryBarrier imageLayoutBarrier = 403 { 404 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 405 DE_NULL, // const void* pNext; 406 (VkAccessFlags)0, // VkAccessFlags srcAccessMask; 407 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; 408 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 409 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 410 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 411 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 412 *m_colorImage, // VkImage image; 413 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 414 }; 415 416 beginCommandBuffer(vk, *m_commandBuffer, 0u); 417 { 418 vk.cmdPipelineBarrier(*m_commandBuffer, 419 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 420 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 421 (VkDependencyFlags)0, 422 0u, DE_NULL, 423 0u, DE_NULL, 424 1u, &imageLayoutBarrier); 425 426 beginRenderPass(vk, *m_commandBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), tcu::Vec4(0.0f)); 427 { 428 const std::vector<VkDeviceSize> vertexBufferOffsets(drawConfig.vertexBuffers.size(), 0ull); 429 430 vk.cmdBindPipeline(*m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline); 431 vk.cmdBindDescriptorSets(*m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet, 0, DE_NULL); 432 vk.cmdBindVertexBuffers(*m_commandBuffer, 0, (deUint32)drawConfig.vertexBuffers.size(), drawConfig.vertexBuffers.data(), vertexBufferOffsets.data()); 433 434 if (drawConfig.indexBuffer == DE_NULL || drawConfig.indexCount == 0) 435 { 436 vk.cmdDraw(*m_commandBuffer, drawConfig.vertexCount, drawConfig.instanceCount, 0, 0); 437 } 438 else 439 { 440 vk.cmdBindIndexBuffer(*m_commandBuffer, drawConfig.indexBuffer, 0, VK_INDEX_TYPE_UINT32); 441 vk.cmdDrawIndexed(*m_commandBuffer, drawConfig.indexCount, drawConfig.instanceCount, 0, 0, 0); 442 } 443 } 444 endRenderPass(vk, *m_commandBuffer); 445 } 446 endCommandBuffer(vk, *m_commandBuffer); 447 } 448 } 449 450 // ComputeEnvironment 451 452 ComputeEnvironment::ComputeEnvironment (Context& context, 453 VkDevice device, 454 VkDescriptorSetLayout descriptorSetLayout, 455 VkDescriptorSet descriptorSet) 456 457 : TestEnvironment (context, device, descriptorSetLayout, descriptorSet) 458 { 459 const DeviceInterface& vk = context.getDeviceInterface(); 460 461 // Create pipeline layout 462 { 463 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 464 { 465 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 466 DE_NULL, // const void* pNext; 467 0u, // VkPipelineLayoutCreateFlags flags; 468 1u, // deUint32 setLayoutCount; 469 &m_descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts; 470 0u, // deUint32 pushConstantRangeCount; 471 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 472 }; 473 474 m_pipelineLayout = createPipelineLayout(vk, m_device, &pipelineLayoutParams); 475 } 476 477 // Create compute pipeline 478 { 479 m_computeShaderModule = createShaderModule(vk, m_device, m_context.getBinaryCollection().get("compute"), 0); 480 481 const VkPipelineShaderStageCreateInfo computeStageParams = 482 { 483 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 484 DE_NULL, // const void* pNext; 485 0u, // VkPipelineShaderStageCreateFlags flags; 486 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage; 487 *m_computeShaderModule, // VkShaderModule module; 488 "main", // const char* pName; 489 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 490 }; 491 492 const VkComputePipelineCreateInfo computePipelineParams = 493 { 494 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType; 495 DE_NULL, // const void* pNext; 496 0u, // VkPipelineCreateFlags flags; 497 computeStageParams, // VkPipelineShaderStageCreateInfo stage; 498 *m_pipelineLayout, // VkPipelineLayout layout; 499 DE_NULL, // VkPipeline basePipelineHandle; 500 0u // deInt32 basePipelineIndex; 501 }; 502 503 m_computePipeline = createComputePipeline(vk, m_device, DE_NULL, &computePipelineParams); 504 } 505 506 // Record commands 507 { 508 beginCommandBuffer(vk, *m_commandBuffer, 0u); 509 vk.cmdBindPipeline(*m_commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline); 510 vk.cmdBindDescriptorSets(*m_commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &m_descriptorSet, 0, DE_NULL); 511 vk.cmdDispatch(*m_commandBuffer, 32, 32, 1); 512 endCommandBuffer(vk, *m_commandBuffer); 513 } 514 } 515 516 } // robustness 517 } // vkt 518