1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * Copyright (c) 2014 The Android Open Source Project 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 Geometry shader instanced rendering tests 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktGeometryInstancedRenderingTests.hpp" 26 #include "vktTestCase.hpp" 27 #include "vktTestCaseUtil.hpp" 28 #include "vktGeometryTestsUtil.hpp" 29 30 #include "vkPrograms.hpp" 31 #include "vkQueryUtil.hpp" 32 #include "vkMemUtil.hpp" 33 #include "vkRefUtil.hpp" 34 #include "vkTypeUtil.hpp" 35 #include "vkImageUtil.hpp" 36 37 #include "tcuTextureUtil.hpp" 38 #include "tcuImageCompare.hpp" 39 #include "tcuTestLog.hpp" 40 41 #include "deRandom.hpp" 42 #include "deMath.h" 43 44 namespace vkt 45 { 46 namespace geometry 47 { 48 namespace 49 { 50 using namespace vk; 51 using de::MovePtr; 52 using de::UniquePtr; 53 using tcu::Vec4; 54 using tcu::UVec2; 55 56 struct TestParams 57 { 58 int numDrawInstances; 59 int numInvocations; 60 }; 61 62 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const VkExtent3D size, const VkImageUsageFlags usage) 63 { 64 const VkImageCreateInfo imageParams = 65 { 66 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 67 DE_NULL, // const void* pNext; 68 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 69 VK_IMAGE_TYPE_2D, // VkImageType imageType; 70 format, // VkFormat format; 71 size, // VkExtent3D extent; 72 1u, // deUint32 mipLevels; 73 1u, // deUint32 arrayLayers; 74 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 75 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 76 usage, // VkImageUsageFlags usage; 77 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 78 0u, // deUint32 queueFamilyIndexCount; 79 DE_NULL, // const deUint32* pQueueFamilyIndices; 80 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 81 }; 82 return imageParams; 83 } 84 85 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, 86 const VkDevice device, 87 const VkFormat colorFormat) 88 { 89 const VkAttachmentDescription colorAttachmentDescription = 90 { 91 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 92 colorFormat, // VkFormat format; 93 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 94 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 95 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 96 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 97 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 98 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 99 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 100 }; 101 102 const VkAttachmentReference colorAttachmentRef = 103 { 104 0u, // deUint32 attachment; 105 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 106 }; 107 108 const VkSubpassDescription subpassDescription = 109 { 110 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 111 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 112 0u, // deUint32 inputAttachmentCount; 113 DE_NULL, // const VkAttachmentReference* pInputAttachments; 114 1u, // deUint32 colorAttachmentCount; 115 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments; 116 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 117 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 118 0u, // deUint32 preserveAttachmentCount; 119 DE_NULL // const deUint32* pPreserveAttachments; 120 }; 121 122 const VkRenderPassCreateInfo renderPassInfo = 123 { 124 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 125 DE_NULL, // const void* pNext; 126 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 127 1u, // deUint32 attachmentCount; 128 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; 129 1u, // deUint32 subpassCount; 130 &subpassDescription, // const VkSubpassDescription* pSubpasses; 131 0u, // deUint32 dependencyCount; 132 DE_NULL // const VkSubpassDependency* pDependencies; 133 }; 134 135 return createRenderPass(vk, device, &renderPassInfo); 136 } 137 138 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 139 const VkDevice device, 140 const VkPipelineLayout pipelineLayout, 141 const VkRenderPass renderPass, 142 const VkShaderModule vertexModule, 143 const VkShaderModule geometryModule, 144 const VkShaderModule fragmentModule, 145 const VkExtent2D renderSize) 146 { 147 const VkVertexInputBindingDescription vertexInputBindingDescription = 148 { 149 0u, // uint32_t binding; 150 sizeof(Vec4), // uint32_t stride; 151 VK_VERTEX_INPUT_RATE_INSTANCE, // VkVertexInputRate inputRate; 152 }; 153 154 const VkVertexInputAttributeDescription vertexInputAttributeDescription = 155 { 156 0u, // uint32_t location; 157 0u, // uint32_t binding; 158 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 159 0u, // uint32_t offset; 160 }; 161 162 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 163 { 164 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 165 DE_NULL, // const void* pNext; 166 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 167 1u, // uint32_t vertexBindingDescriptionCount; 168 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 169 1u, // uint32_t vertexAttributeDescriptionCount; 170 &vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 171 }; 172 173 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 174 { 175 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 176 DE_NULL, // const void* pNext; 177 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 178 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology; 179 VK_FALSE, // VkBool32 primitiveRestartEnable; 180 }; 181 182 const VkViewport viewport = makeViewport( 183 0.0f, 0.0f, 184 static_cast<float>(renderSize.width), static_cast<float>(renderSize.height), 185 0.0f, 1.0f); 186 const VkRect2D scissor = 187 { 188 makeOffset2D(0, 0), 189 makeExtent2D(renderSize.width, renderSize.height), 190 }; 191 192 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 193 { 194 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 195 DE_NULL, // const void* pNext; 196 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 197 1u, // uint32_t viewportCount; 198 &viewport, // const VkViewport* pViewports; 199 1u, // uint32_t scissorCount; 200 &scissor, // const VkRect2D* pScissors; 201 }; 202 203 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 204 { 205 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 206 DE_NULL, // const void* pNext; 207 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 208 VK_FALSE, // VkBool32 depthClampEnable; 209 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 210 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 211 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 212 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 213 VK_FALSE, // VkBool32 depthBiasEnable; 214 0.0f, // float depthBiasConstantFactor; 215 0.0f, // float depthBiasClamp; 216 0.0f, // float depthBiasSlopeFactor; 217 1.0f, // float lineWidth; 218 }; 219 220 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 221 { 222 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 223 DE_NULL, // const void* pNext; 224 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 225 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 226 VK_FALSE, // VkBool32 sampleShadingEnable; 227 0.0f, // float minSampleShading; 228 DE_NULL, // const VkSampleMask* pSampleMask; 229 VK_FALSE, // VkBool32 alphaToCoverageEnable; 230 VK_FALSE // VkBool32 alphaToOneEnable; 231 }; 232 233 const VkStencilOpState stencilOpState = makeStencilOpState( 234 VK_STENCIL_OP_KEEP, // stencil fail 235 VK_STENCIL_OP_KEEP, // depth & stencil pass 236 VK_STENCIL_OP_KEEP, // depth only fail 237 VK_COMPARE_OP_ALWAYS, // compare op 238 0u, // compare mask 239 0u, // write mask 240 0u); // reference 241 242 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 243 { 244 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 245 DE_NULL, // const void* pNext; 246 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 247 VK_FALSE, // VkBool32 depthTestEnable; 248 VK_FALSE, // VkBool32 depthWriteEnable; 249 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 250 VK_FALSE, // VkBool32 depthBoundsTestEnable; 251 VK_FALSE, // VkBool32 stencilTestEnable; 252 stencilOpState, // VkStencilOpState front; 253 stencilOpState, // VkStencilOpState back; 254 0.0f, // float minDepthBounds; 255 1.0f, // float maxDepthBounds; 256 }; 257 258 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 259 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 260 { 261 VK_FALSE, // VkBool32 blendEnable; 262 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 263 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 264 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 265 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 266 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 267 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 268 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 269 }; 270 271 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 272 { 273 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 274 DE_NULL, // const void* pNext; 275 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 276 VK_FALSE, // VkBool32 logicOpEnable; 277 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 278 1u, // deUint32 attachmentCount; 279 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 280 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 281 }; 282 283 const VkPipelineShaderStageCreateInfo pShaderStages[] = 284 { 285 { 286 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 287 DE_NULL, // const void* pNext; 288 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 289 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 290 vertexModule, // VkShaderModule module; 291 "main", // const char* pName; 292 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 293 }, 294 { 295 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 296 DE_NULL, // const void* pNext; 297 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 298 VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage; 299 geometryModule, // VkShaderModule module; 300 "main", // const char* pName; 301 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 302 }, 303 { 304 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 305 DE_NULL, // const void* pNext; 306 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 307 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 308 fragmentModule, // VkShaderModule module; 309 "main", // const char* pName; 310 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 311 }, 312 }; 313 314 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = 315 { 316 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 317 DE_NULL, // const void* pNext; 318 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 319 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; 320 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 321 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 322 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 323 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 324 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; 325 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 326 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 327 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 328 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 329 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 330 pipelineLayout, // VkPipelineLayout layout; 331 renderPass, // VkRenderPass renderPass; 332 0u, // deUint32 subpass; 333 DE_NULL, // VkPipeline basePipelineHandle; 334 0, // deInt32 basePipelineIndex; 335 }; 336 337 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 338 } 339 340 void draw (Context& context, 341 const UVec2& renderSize, 342 const VkFormat colorFormat, 343 const Vec4& clearColor, 344 const VkBuffer colorBuffer, 345 const int numDrawInstances, 346 const std::vector<Vec4>& perInstanceAttribute) 347 { 348 const DeviceInterface& vk = context.getDeviceInterface(); 349 const VkDevice device = context.getDevice(); 350 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 351 const VkQueue queue = context.getUniversalQueue(); 352 Allocator& allocator = context.getDefaultAllocator(); 353 354 const VkImageSubresourceRange colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); 355 const VkExtent3D colorImageExtent (makeExtent3D(renderSize.x(), renderSize.y(), 1u)); 356 const VkExtent2D renderExtent (makeExtent2D(renderSize.x(), renderSize.y())); 357 358 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(colorFormat, colorImageExtent, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT))); 359 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any)); 360 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)); 361 362 const VkDeviceSize vertexBufferSize = sizeInBytes(perInstanceAttribute); 363 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))); 364 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible)); 365 366 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u)); 367 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u)); 368 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u)); 369 370 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat)); 371 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, renderSize.x(), renderSize.y(), 1u)); 372 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device)); 373 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, renderExtent)); 374 375 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 376 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 377 378 // Initialize vertex data 379 { 380 deMemcpy(vertexBufferAlloc->getHostPtr(), &perInstanceAttribute[0], (size_t)vertexBufferSize); 381 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize); 382 } 383 384 beginCommandBuffer(vk, *cmdBuffer); 385 386 const VkClearValue clearValue = makeClearValueColor(clearColor); 387 const VkRect2D renderArea = 388 { 389 makeOffset2D(0, 0), 390 renderExtent, 391 }; 392 const VkRenderPassBeginInfo renderPassBeginInfo = 393 { 394 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 395 DE_NULL, // const void* pNext; 396 *renderPass, // VkRenderPass renderPass; 397 *framebuffer, // VkFramebuffer framebuffer; 398 renderArea, // VkRect2D renderArea; 399 1u, // uint32_t clearValueCount; 400 &clearValue, // const VkClearValue* pClearValues; 401 }; 402 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 403 404 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 405 { 406 const VkDeviceSize offset = 0ull; 407 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &offset); 408 } 409 vk.cmdDraw(*cmdBuffer, 1u, static_cast<deUint32>(numDrawInstances), 0u, 0u); 410 vk.cmdEndRenderPass(*cmdBuffer); 411 412 // Prepare color image for copy 413 { 414 const VkImageMemoryBarrier barriers[] = 415 { 416 { 417 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 418 DE_NULL, // const void* pNext; 419 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask; 420 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask; 421 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 422 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 423 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 424 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 425 *colorImage, // VkImage image; 426 colorSubresourceRange, // VkImageSubresourceRange subresourceRange; 427 }, 428 }; 429 430 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 431 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 432 } 433 // Color image -> host buffer 434 { 435 const VkBufferImageCopy region = 436 { 437 0ull, // VkDeviceSize bufferOffset; 438 0u, // uint32_t bufferRowLength; 439 0u, // uint32_t bufferImageHeight; 440 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; 441 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 442 colorImageExtent, // VkExtent3D imageExtent; 443 }; 444 445 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer, 1u, ®ion); 446 } 447 // Buffer write barrier 448 { 449 const VkBufferMemoryBarrier barriers[] = 450 { 451 { 452 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 453 DE_NULL, // const void* pNext; 454 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 455 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 456 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 457 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 458 colorBuffer, // VkBuffer buffer; 459 0ull, // VkDeviceSize offset; 460 VK_WHOLE_SIZE, // VkDeviceSize size; 461 }, 462 }; 463 464 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 465 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u); 466 } 467 468 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 469 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 470 } 471 472 std::vector<Vec4> generatePerInstancePosition (const int numInstances) 473 { 474 de::Random rng(1234); 475 std::vector<Vec4> positions; 476 477 for (int i = 0; i < numInstances; ++i) 478 { 479 const float flipX = rng.getBool() ? 1.0f : -1.0f; 480 const float flipY = rng.getBool() ? 1.0f : -1.0f; 481 const float x = flipX * rng.getFloat(0.1f, 0.9f); // x mustn't be 0.0, because we are using sign() in the shader 482 const float y = flipY * rng.getFloat(0.0f, 0.7f); 483 484 positions.push_back(Vec4(x, y, 0.0f, 1.0f)); 485 } 486 487 return positions; 488 } 489 490 //! Get a rectangle region of an image, using NDC coordinates (i.e. [-1, 1] range). 491 //! Result rect is cropped in either dimension to be inside the bounds of the image. 492 tcu::PixelBufferAccess getSubregion (tcu::PixelBufferAccess image, const float x, const float y, const float size) 493 { 494 const float w = static_cast<float>(image.getWidth()); 495 const float h = static_cast<float>(image.getHeight()); 496 const float x1 = w * (x + 1.0f) * 0.5f; 497 const float y1 = h * (y + 1.0f) * 0.5f; 498 const float sx = w * size * 0.5f; 499 const float sy = h * size * 0.5f; 500 const float x2 = x1 + sx; 501 const float y2 = y1 + sy; 502 503 // Round and clamp only after all of the above. 504 const int ix1 = std::max(deRoundFloatToInt32(x1), 0); 505 const int ix2 = std::min(deRoundFloatToInt32(x2), image.getWidth()); 506 const int iy1 = std::max(deRoundFloatToInt32(y1), 0); 507 const int iy2 = std::min(deRoundFloatToInt32(y2), image.getHeight()); 508 509 return tcu::getSubregion(image, ix1, iy1, ix2 - ix1, iy2 - iy1); 510 } 511 512 //! Must be in sync with the geometry shader code. 513 void generateReferenceImage(tcu::PixelBufferAccess image, const Vec4& clearColor, const std::vector<Vec4>& perInstancePosition, const int numInvocations) 514 { 515 tcu::clear(image, clearColor); 516 517 for (std::vector<Vec4>::const_iterator iterPosition = perInstancePosition.begin(); iterPosition != perInstancePosition.end(); ++iterPosition) 518 for (int invocationNdx = 0; invocationNdx < numInvocations; ++invocationNdx) 519 { 520 const float x = iterPosition->x(); 521 const float y = iterPosition->y(); 522 const float modifier = (numInvocations > 1 ? static_cast<float>(invocationNdx) / static_cast<float>(numInvocations - 1) : 0.0f); 523 const Vec4 color (deFloatAbs(x), deFloatAbs(y), 0.2f + 0.8f * modifier, 1.0f); 524 const float size = 0.05f + 0.03f * modifier; 525 const float dx = (deFloatSign(-x) - x) / static_cast<float>(numInvocations); 526 const float xOffset = static_cast<float>(invocationNdx) * dx; 527 const float yOffset = 0.3f * deFloatSin(12.0f * modifier); 528 529 tcu::PixelBufferAccess rect = getSubregion(image, x + xOffset - size, y + yOffset - size, size + size); 530 tcu::clear(rect, color); 531 } 532 } 533 534 void initPrograms (SourceCollections& programCollection, const TestParams params) 535 { 536 // Vertex shader 537 { 538 std::ostringstream src; 539 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 540 << "\n" 541 << "layout(location = 0) in vec4 in_position;\n" 542 << "\n" 543 << "out gl_PerVertex {\n" 544 << " vec4 gl_Position;\n" 545 << "};\n" 546 << "\n" 547 << "void main(void)\n" 548 << "{\n" 549 << " gl_Position = in_position;\n" 550 << "}\n"; 551 552 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 553 } 554 555 // Geometry shader 556 { 557 // The shader must be in sync with reference image rendering routine. 558 559 std::ostringstream src; 560 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 561 << "\n" 562 << "layout(points, invocations = " << params.numInvocations << ") in;\n" 563 << "layout(triangle_strip, max_vertices = 4) out;\n" 564 << "\n" 565 << "layout(location = 0) out vec4 out_color;\n" 566 << "\n" 567 << "in gl_PerVertex {\n" 568 << " vec4 gl_Position;\n" 569 << "} gl_in[];\n" 570 << "\n" 571 << "out gl_PerVertex {\n" 572 << " vec4 gl_Position;\n" 573 << "};\n" 574 << "\n" 575 << "void main(void)\n" 576 << "{\n" 577 << " const vec4 pos = gl_in[0].gl_Position;\n" 578 << " const float modifier = " << (params.numInvocations > 1 ? "float(gl_InvocationID) / float(" + de::toString(params.numInvocations - 1) + ")" : "0.0") << ";\n" 579 << " const vec4 color = vec4(abs(pos.x), abs(pos.y), 0.2 + 0.8 * modifier, 1.0);\n" 580 << " const float size = 0.05 + 0.03 * modifier;\n" 581 << " const float dx = (sign(-pos.x) - pos.x) / float(" << params.numInvocations << ");\n" 582 << " const vec4 offsetPos = pos + vec4(float(gl_InvocationID) * dx,\n" 583 << " 0.3 * sin(12.0 * modifier),\n" 584 << " 0.0,\n" 585 << " 0.0);\n" 586 << "\n" 587 << " gl_Position = offsetPos + vec4(-size, -size, 0.0, 0.0);\n" 588 << " out_color = color;\n" 589 << " EmitVertex();\n" 590 << "\n" 591 << " gl_Position = offsetPos + vec4(-size, size, 0.0, 0.0);\n" 592 << " out_color = color;\n" 593 << " EmitVertex();\n" 594 << "\n" 595 << " gl_Position = offsetPos + vec4( size, -size, 0.0, 0.0);\n" 596 << " out_color = color;\n" 597 << " EmitVertex();\n" 598 << "\n" 599 << " gl_Position = offsetPos + vec4( size, size, 0.0, 0.0);\n" 600 << " out_color = color;\n" 601 << " EmitVertex();\n" 602 << "}\n"; 603 604 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str()); 605 } 606 607 // Fragment shader 608 { 609 std::ostringstream src; 610 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 611 << "\n" 612 << "layout(location = 0) in vec4 in_color;\n" 613 << "layout(location = 0) out vec4 o_color;\n" 614 << "\n" 615 << "void main(void)\n" 616 << "{\n" 617 << " o_color = in_color;\n" 618 << "}\n"; 619 620 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 621 } 622 } 623 624 tcu::TestStatus test (Context& context, const TestParams params) 625 { 626 const DeviceInterface& vk = context.getDeviceInterface(); 627 const InstanceInterface& vki = context.getInstanceInterface(); 628 const VkDevice device = context.getDevice(); 629 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 630 Allocator& allocator = context.getDefaultAllocator(); 631 632 checkGeometryShaderSupport(vki, physDevice, params.numInvocations); 633 634 const UVec2 renderSize (128u, 128u); 635 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 636 const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f); 637 638 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); 639 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT))); 640 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); 641 642 const std::vector<Vec4> perInstancePosition = generatePerInstancePosition(params.numDrawInstances); 643 644 { 645 context.getTestContext().getLog() 646 << tcu::TestLog::Message << "Rendering " << params.numDrawInstances << " instance(s) of colorful quads." << tcu::TestLog::EndMessage 647 << tcu::TestLog::Message << "Drawing " << params.numInvocations << " quad(s), each drawn by a geometry shader invocation." << tcu::TestLog::EndMessage; 648 } 649 650 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize); 651 draw(context, renderSize, colorFormat, clearColor, *colorBuffer, params.numDrawInstances, perInstancePosition); 652 653 // Compare result 654 { 655 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize); 656 const tcu::ConstPixelBufferAccess result(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr()); 657 658 tcu::TextureLevel reference(mapVkFormat(colorFormat), renderSize.x(), renderSize.y()); 659 generateReferenceImage(reference.getAccess(), clearColor, perInstancePosition, params.numInvocations); 660 661 if (!tcu::fuzzyCompare(context.getTestContext().getLog(), "Image Compare", "Image Compare", reference.getAccess(), result, 0.01f, tcu::COMPARE_LOG_RESULT)) 662 return tcu::TestStatus::fail("Rendered image is incorrect"); 663 else 664 return tcu::TestStatus::pass("OK"); 665 } 666 } 667 668 } // anonymous 669 670 //! \note CTS requires shaders to be known ahead of time (some platforms use precompiled shaders), so we can't query a limit at runtime and generate 671 //! a shader based on that. This applies to number of GS invocations which can't be injected into the shader. 672 tcu::TestCaseGroup* createInstancedRenderingTests (tcu::TestContext& testCtx) 673 { 674 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "instanced", "Instanced rendering tests.")); 675 676 const int drawInstanceCases[] = 677 { 678 1, 2, 4, 8, 679 }; 680 const int invocationCases[] = 681 { 682 1, 2, 8, 32, // required by the Vulkan spec 683 64, 127, // larger than the minimum, but perhaps some implementations support it, so we'll try 684 }; 685 686 for (const int* pNumDrawInstances = drawInstanceCases; pNumDrawInstances != drawInstanceCases + DE_LENGTH_OF_ARRAY(drawInstanceCases); ++pNumDrawInstances) 687 for (const int* pNumInvocations = invocationCases; pNumInvocations != invocationCases + DE_LENGTH_OF_ARRAY(invocationCases); ++pNumInvocations) 688 { 689 std::ostringstream caseName; 690 caseName << "draw_" << *pNumDrawInstances << "_instances_" << *pNumInvocations << "_geometry_invocations"; 691 692 const TestParams params = 693 { 694 *pNumDrawInstances, 695 *pNumInvocations, 696 }; 697 698 addFunctionCaseWithPrograms(group.get(), caseName.str(), "", initPrograms, test, params); 699 } 700 701 return group.release(); 702 } 703 704 } // geometry 705 } // vkt 706