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