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 Scissor tests 23 *//*--------------------------------------------------------------------*/ 24 25#include "vktFragmentOperationsScissorTests.hpp" 26#include "vktFragmentOperationsScissorMultiViewportTests.hpp" 27#include "vktTestCaseUtil.hpp" 28#include "vktTestGroupUtil.hpp" 29#include "vktFragmentOperationsMakeUtil.hpp" 30 31#include "vkDefs.hpp" 32#include "vkRefUtil.hpp" 33#include "vkTypeUtil.hpp" 34#include "vkMemUtil.hpp" 35#include "vkPrograms.hpp" 36#include "vkImageUtil.hpp" 37 38#include "tcuTestLog.hpp" 39#include "tcuVector.hpp" 40#include "tcuImageCompare.hpp" 41 42#include "deUniquePtr.hpp" 43#include "deRandom.hpp" 44 45namespace vkt 46{ 47namespace FragmentOperations 48{ 49using namespace vk; 50using de::UniquePtr; 51using de::MovePtr; 52using tcu::Vec4; 53using tcu::Vec2; 54using tcu::IVec2; 55using tcu::IVec4; 56 57namespace 58{ 59 60//! What primitives will be drawn by the test case. 61enum TestPrimitive 62{ 63 TEST_PRIMITIVE_POINTS, //!< Many points. 64 TEST_PRIMITIVE_LINES, //!< Many short lines. 65 TEST_PRIMITIVE_TRIANGLES, //!< Many small triangles. 66 TEST_PRIMITIVE_BIG_LINE, //!< One line crossing the whole render area. 67 TEST_PRIMITIVE_BIG_TRIANGLE, //!< One triangle covering the whole render area. 68}; 69 70struct VertexData 71{ 72 Vec4 position; 73 Vec4 color; 74}; 75 76//! Parameters used by the test case. 77struct CaseDef 78{ 79 Vec4 renderArea; //!< (ox, oy, w, h), where origin (0,0) is the top-left corner of the viewport. Width and height are in range [0, 1]. 80 Vec4 scissorArea; //!< scissored area (ox, oy, w, h) 81 TestPrimitive primitive; 82}; 83 84template<typename T> 85inline VkDeviceSize sizeInBytes(const std::vector<T>& vec) 86{ 87 return vec.size() * sizeof(vec[0]); 88} 89 90VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const IVec2& size, VkImageUsageFlags usage) 91{ 92 const VkImageCreateInfo imageParams = 93 { 94 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 95 DE_NULL, // const void* pNext; 96 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 97 VK_IMAGE_TYPE_2D, // VkImageType imageType; 98 format, // VkFormat format; 99 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 100 1u, // deUint32 mipLevels; 101 1u, // deUint32 arrayLayers; 102 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 103 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 104 usage, // VkImageUsageFlags usage; 105 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 106 0u, // deUint32 queueFamilyIndexCount; 107 DE_NULL, // const deUint32* pQueueFamilyIndices; 108 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 109 }; 110 return imageParams; 111} 112 113//! A single-attachment, single-subpass render pass. 114Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, 115 const VkDevice device, 116 const VkFormat colorFormat) 117{ 118 const VkAttachmentDescription colorAttachmentDescription = 119 { 120 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 121 colorFormat, // VkFormat format; 122 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 123 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 124 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 125 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 126 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 127 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 128 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 129 }; 130 131 const VkAttachmentReference colorAttachmentRef = 132 { 133 0u, // deUint32 attachment; 134 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 135 }; 136 137 const VkSubpassDescription subpassDescription = 138 { 139 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 140 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 141 0u, // deUint32 inputAttachmentCount; 142 DE_NULL, // const VkAttachmentReference* pInputAttachments; 143 1u, // deUint32 colorAttachmentCount; 144 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments; 145 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 146 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 147 0u, // deUint32 preserveAttachmentCount; 148 DE_NULL // const deUint32* pPreserveAttachments; 149 }; 150 151 const VkRenderPassCreateInfo renderPassInfo = 152 { 153 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 154 DE_NULL, // const void* pNext; 155 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 156 1u, // deUint32 attachmentCount; 157 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; 158 1u, // deUint32 subpassCount; 159 &subpassDescription, // const VkSubpassDescription* pSubpasses; 160 0u, // deUint32 dependencyCount; 161 DE_NULL // const VkSubpassDependency* pDependencies; 162 }; 163 164 return createRenderPass(vk, device, &renderPassInfo); 165} 166 167Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 168 const VkDevice device, 169 const VkPipelineLayout pipelineLayout, 170 const VkRenderPass renderPass, 171 const VkShaderModule vertexModule, 172 const VkShaderModule fragmentModule, 173 const IVec2 renderSize, 174 const IVec4 scissorArea, //!< (ox, oy, w, h) 175 const VkPrimitiveTopology topology) 176{ 177 const VkVertexInputBindingDescription vertexInputBindingDescription = 178 { 179 0u, // uint32_t binding; 180 sizeof(VertexData), // uint32_t stride; 181 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 182 }; 183 184 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = 185 { 186 { 187 0u, // uint32_t location; 188 0u, // uint32_t binding; 189 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 190 0u, // uint32_t offset; 191 }, 192 { 193 1u, // uint32_t location; 194 0u, // uint32_t binding; 195 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 196 sizeof(Vec4), // uint32_t offset; 197 }, 198 }; 199 200 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 201 { 202 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 203 DE_NULL, // const void* pNext; 204 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 205 1u, // uint32_t vertexBindingDescriptionCount; 206 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 207 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount; 208 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 209 }; 210 211 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 212 { 213 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 214 DE_NULL, // const void* pNext; 215 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 216 topology, // VkPrimitiveTopology topology; 217 VK_FALSE, // VkBool32 primitiveRestartEnable; 218 }; 219 220 const VkViewport viewport = makeViewport( 221 0.0f, 0.0f, 222 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 223 0.0f, 1.0f); 224 225 const VkRect2D scissor = { 226 makeOffset2D(scissorArea.x(), scissorArea.y()), 227 makeExtent2D(static_cast<deUint32>(scissorArea.z()), static_cast<deUint32>(scissorArea.w())), 228 }; 229 230 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 231 { 232 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 233 DE_NULL, // const void* pNext; 234 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 235 1u, // uint32_t viewportCount; 236 &viewport, // const VkViewport* pViewports; 237 1u, // uint32_t scissorCount; 238 &scissor, // const VkRect2D* pScissors; 239 }; 240 241 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 242 { 243 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 244 DE_NULL, // const void* pNext; 245 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 246 VK_FALSE, // VkBool32 depthClampEnable; 247 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 248 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 249 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 250 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 251 VK_FALSE, // VkBool32 depthBiasEnable; 252 0.0f, // float depthBiasConstantFactor; 253 0.0f, // float depthBiasClamp; 254 0.0f, // float depthBiasSlopeFactor; 255 1.0f, // float lineWidth; 256 }; 257 258 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 259 { 260 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 261 DE_NULL, // const void* pNext; 262 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 263 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 264 VK_FALSE, // VkBool32 sampleShadingEnable; 265 0.0f, // float minSampleShading; 266 DE_NULL, // const VkSampleMask* pSampleMask; 267 VK_FALSE, // VkBool32 alphaToCoverageEnable; 268 VK_FALSE // VkBool32 alphaToOneEnable; 269 }; 270 271 const VkStencilOpState stencilOpState = makeStencilOpState( 272 VK_STENCIL_OP_KEEP, // stencil fail 273 VK_STENCIL_OP_KEEP, // depth & stencil pass 274 VK_STENCIL_OP_KEEP, // depth only fail 275 VK_COMPARE_OP_ALWAYS, // compare op 276 0u, // compare mask 277 0u, // write mask 278 0u); // reference 279 280 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 281 { 282 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 283 DE_NULL, // const void* pNext; 284 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 285 VK_FALSE, // VkBool32 depthTestEnable; 286 VK_FALSE, // VkBool32 depthWriteEnable; 287 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 288 VK_FALSE, // VkBool32 depthBoundsTestEnable; 289 VK_FALSE, // VkBool32 stencilTestEnable; 290 stencilOpState, // VkStencilOpState front; 291 stencilOpState, // VkStencilOpState back; 292 0.0f, // float minDepthBounds; 293 1.0f, // float maxDepthBounds; 294 }; 295 296 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 297 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 298 { 299 VK_FALSE, // VkBool32 blendEnable; 300 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 301 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 302 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 303 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 304 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 305 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 306 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 307 }; 308 309 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 310 { 311 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 312 DE_NULL, // const void* pNext; 313 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 314 VK_FALSE, // VkBool32 logicOpEnable; 315 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 316 1u, // deUint32 attachmentCount; 317 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 318 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 319 }; 320 321 const VkPipelineShaderStageCreateInfo pShaderStages[] = 322 { 323 { 324 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 325 DE_NULL, // const void* pNext; 326 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 327 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 328 vertexModule, // VkShaderModule module; 329 "main", // const char* pName; 330 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 331 }, 332 { 333 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 334 DE_NULL, // const void* pNext; 335 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 336 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 337 fragmentModule, // VkShaderModule module; 338 "main", // const char* pName; 339 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 340 } 341 }; 342 343 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = 344 { 345 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 346 DE_NULL, // const void* pNext; 347 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 348 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; 349 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 350 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 351 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 352 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 353 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; 354 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 355 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 356 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 357 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 358 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 359 pipelineLayout, // VkPipelineLayout layout; 360 renderPass, // VkRenderPass renderPass; 361 0u, // deUint32 subpass; 362 DE_NULL, // VkPipeline basePipelineHandle; 363 0, // deInt32 basePipelineIndex; 364 }; 365 366 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 367} 368 369inline VertexData makeVertex (const float x, const float y, const Vec4& color) 370{ 371 const VertexData data = { Vec4(x, y, 0.0f, 1.0f), color }; 372 return data; 373} 374 375std::vector<VertexData> genVertices (const TestPrimitive primitive, const Vec4& renderArea, const Vec4& primitiveColor) 376{ 377 std::vector<VertexData> vertices; 378 de::Random rng (1234); 379 380 const float x0 = 2.0f * renderArea.x() - 1.0f; 381 const float y0 = 2.0f * renderArea.y() - 1.0f; 382 const float rx = 2.0f * renderArea.z(); 383 const float ry = 2.0f * renderArea.w(); 384 const float size = 0.2f; 385 386 switch (primitive) 387 { 388 case TEST_PRIMITIVE_POINTS: 389 for (int i = 0; i < 50; ++i) 390 { 391 const float x = x0 + rng.getFloat(0.0f, rx); 392 const float y = y0 + rng.getFloat(0.0f, ry); 393 vertices.push_back(makeVertex(x, y, primitiveColor)); 394 } 395 break; 396 397 case TEST_PRIMITIVE_LINES: 398 for (int i = 0; i < 30; ++i) 399 { 400 const float x = x0 + rng.getFloat(0.0f, rx - size); 401 const float y = y0 + rng.getFloat(0.0f, ry - size); 402 vertices.push_back(makeVertex(x, y, primitiveColor)); 403 vertices.push_back(makeVertex(x + size, y + size, primitiveColor)); 404 } 405 break; 406 407 case TEST_PRIMITIVE_TRIANGLES: 408 for (int i = 0; i < 20; ++i) 409 { 410 const float x = x0 + rng.getFloat(0.0f, rx - size); 411 const float y = y0 + rng.getFloat(0.0f, ry - size); 412 vertices.push_back(makeVertex(x, y, primitiveColor)); 413 vertices.push_back(makeVertex(x + size/2.0f, y + size, primitiveColor)); 414 vertices.push_back(makeVertex(x + size, y, primitiveColor)); 415 } 416 break; 417 418 case TEST_PRIMITIVE_BIG_LINE: 419 vertices.push_back(makeVertex(x0, y0, primitiveColor)); 420 vertices.push_back(makeVertex(x0 + rx, y0 + ry, primitiveColor)); 421 break; 422 423 case TEST_PRIMITIVE_BIG_TRIANGLE: 424 vertices.push_back(makeVertex(x0, y0, primitiveColor)); 425 vertices.push_back(makeVertex(x0 + rx/2.0f, y0 + ry, primitiveColor)); 426 vertices.push_back(makeVertex(x0 + rx, y0, primitiveColor)); 427 break; 428 } 429 430 return vertices; 431} 432 433VkPrimitiveTopology getTopology (const TestPrimitive primitive) 434{ 435 switch (primitive) 436 { 437 case TEST_PRIMITIVE_POINTS: return VK_PRIMITIVE_TOPOLOGY_POINT_LIST; 438 439 case TEST_PRIMITIVE_LINES: 440 case TEST_PRIMITIVE_BIG_LINE: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; 441 442 case TEST_PRIMITIVE_TRIANGLES: 443 case TEST_PRIMITIVE_BIG_TRIANGLE: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 444 445 default: 446 DE_ASSERT(0); 447 return VK_PRIMITIVE_TOPOLOGY_LAST; 448 } 449} 450 451void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize size) 452{ 453 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(size)); 454 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), size); 455} 456 457//! Transform from normalized coords to framebuffer space. 458inline IVec4 getAreaRect (const Vec4& area, const int width, const int height) 459{ 460 return IVec4(static_cast<deInt32>(static_cast<float>(width) * area.x()), 461 static_cast<deInt32>(static_cast<float>(height) * area.y()), 462 static_cast<deInt32>(static_cast<float>(width) * area.z()), 463 static_cast<deInt32>(static_cast<float>(height) * area.w())); 464} 465 466void applyScissor (tcu::PixelBufferAccess imageAccess, const Vec4& floatScissorArea, const Vec4& clearColor) 467{ 468 const IVec4 scissorRect (getAreaRect(floatScissorArea, imageAccess.getWidth(), imageAccess.getHeight())); 469 const int sx0 = scissorRect.x(); 470 const int sx1 = scissorRect.x() + scissorRect.z(); 471 const int sy0 = scissorRect.y(); 472 const int sy1 = scissorRect.y() + scissorRect.w(); 473 474 for (int y = 0; y < imageAccess.getHeight(); ++y) 475 for (int x = 0; x < imageAccess.getWidth(); ++x) 476 { 477 // Fragments outside fail the scissor test. 478 if (x < sx0 || x >= sx1 || y < sy0 || y >= sy1) 479 imageAccess.setPixel(clearColor, x, y); 480 } 481} 482 483void initPrograms (SourceCollections& programCollection, const CaseDef caseDef) 484{ 485 DE_UNREF(caseDef); 486 487 // Vertex shader 488 { 489 const bool usePointSize = (caseDef.primitive == TEST_PRIMITIVE_POINTS); 490 491 std::ostringstream src; 492 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 493 << "\n" 494 << "layout(location = 0) in vec4 in_position;\n" 495 << "layout(location = 1) in vec4 in_color;\n" 496 << "layout(location = 0) out vec4 o_color;\n" 497 << "\n" 498 << "out gl_PerVertex {\n" 499 << " vec4 gl_Position;\n" 500 << (usePointSize ? " float gl_PointSize;\n" : "") 501 << "};\n" 502 << "\n" 503 << "void main(void)\n" 504 << "{\n" 505 << " gl_Position = in_position;\n" 506 << (usePointSize ? " gl_PointSize = 1.0;\n" : "") 507 << " o_color = in_color;\n" 508 << "}\n"; 509 510 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 511 } 512 513 // Fragment shader 514 { 515 std::ostringstream src; 516 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 517 << "\n" 518 << "layout(location = 0) in vec4 in_color;\n" 519 << "layout(location = 0) out vec4 o_color;\n" 520 << "\n" 521 << "void main(void)\n" 522 << "{\n" 523 << " o_color = in_color;\n" 524 << "}\n"; 525 526 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 527 } 528} 529 530class ScissorRenderer 531{ 532public: 533 ScissorRenderer (Context& context, const CaseDef caseDef, const IVec2& renderSize, const VkFormat colorFormat, const Vec4& primitiveColor, const Vec4& clearColor) 534 : m_renderSize (renderSize) 535 , m_colorFormat (colorFormat) 536 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)) 537 , m_primitiveColor (primitiveColor) 538 , m_clearColor (clearColor) 539 , m_vertices (genVertices(caseDef.primitive, caseDef.renderArea, m_primitiveColor)) 540 , m_vertexBufferSize (sizeInBytes(m_vertices)) 541 , m_topology (getTopology(caseDef.primitive)) 542 { 543 const DeviceInterface& vk = context.getDeviceInterface(); 544 const VkDevice device = context.getDevice(); 545 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 546 Allocator& allocator = context.getDefaultAllocator(); 547 548 m_colorImage = makeImage(vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)); 549 m_colorImageAlloc = bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any); 550 m_colorAttachment = makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange); 551 552 m_vertexBuffer = makeBuffer(vk, device, makeBufferCreateInfo(m_vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); 553 m_vertexBufferAlloc = bindBuffer(vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible); 554 555 { 556 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], static_cast<std::size_t>(m_vertexBufferSize)); 557 flushMappedMemoryRange(vk, device, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), m_vertexBufferSize); 558 } 559 560 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u); 561 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u); 562 m_renderPass = makeRenderPass (vk, device, m_colorFormat); 563 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, 1u, &m_colorAttachment.get(), 564 static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y())); 565 m_pipelineLayout = makePipelineLayout (vk, device); 566 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex); 567 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 568 569 } 570 571 void draw (Context& context, const Vec4& scissorAreaFloat, const VkBuffer colorBuffer) const 572 { 573 const DeviceInterface& vk = context.getDeviceInterface(); 574 const VkDevice device = context.getDevice(); 575 const VkQueue queue = context.getUniversalQueue(); 576 577 // New pipeline, because we're modifying scissor (we don't use dynamic state). 578 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_fragmentModule, 579 m_renderSize, getAreaRect(scissorAreaFloat, m_renderSize.x(), m_renderSize.y()), m_topology)); 580 581 beginCommandBuffer(vk, *m_cmdBuffer); 582 583 const VkClearValue clearValue = makeClearValueColor(m_clearColor); 584 const VkRect2D renderArea = 585 { 586 makeOffset2D(0, 0), 587 makeExtent2D(m_renderSize.x(), m_renderSize.y()), 588 }; 589 const VkRenderPassBeginInfo renderPassBeginInfo = 590 { 591 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 592 DE_NULL, // const void* pNext; 593 *m_renderPass, // VkRenderPass renderPass; 594 *m_framebuffer, // VkFramebuffer framebuffer; 595 renderArea, // VkRect2D renderArea; 596 1u, // uint32_t clearValueCount; 597 &clearValue, // const VkClearValue* pClearValues; 598 }; 599 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 600 601 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 602 { 603 const VkDeviceSize vertexBufferOffset = 0ull; 604 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset); 605 } 606 607 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_vertices.size()), 1u, 0u, 0u); 608 vk.cmdEndRenderPass(*m_cmdBuffer); 609 610 // Prepare color image for copy 611 { 612 const VkImageMemoryBarrier barriers[] = 613 { 614 { 615 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 616 DE_NULL, // const void* pNext; 617 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask; 618 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask; 619 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 620 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 621 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 622 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 623 *m_colorImage, // VkImage image; 624 m_colorSubresourceRange, // VkImageSubresourceRange subresourceRange; 625 }, 626 }; 627 628 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 629 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 630 } 631 // Color image -> host buffer 632 { 633 const VkBufferImageCopy region = 634 { 635 0ull, // VkDeviceSize bufferOffset; 636 0u, // uint32_t bufferRowLength; 637 0u, // uint32_t bufferImageHeight; 638 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; 639 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 640 makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u), // VkExtent3D imageExtent; 641 }; 642 643 vk.cmdCopyImageToBuffer(*m_cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer, 1u, ®ion); 644 } 645 // Buffer write barrier 646 { 647 const VkBufferMemoryBarrier barriers[] = 648 { 649 { 650 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 651 DE_NULL, // const void* pNext; 652 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 653 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 654 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 655 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 656 colorBuffer, // VkBuffer buffer; 657 0ull, // VkDeviceSize offset; 658 VK_WHOLE_SIZE, // VkDeviceSize size; 659 }, 660 }; 661 662 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 663 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u); 664 } 665 666 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer)); 667 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer); 668 } 669 670private: 671 const IVec2 m_renderSize; 672 const VkFormat m_colorFormat; 673 const VkImageSubresourceRange m_colorSubresourceRange; 674 const Vec4 m_primitiveColor; 675 const Vec4 m_clearColor; 676 const std::vector<VertexData> m_vertices; 677 const VkDeviceSize m_vertexBufferSize; 678 const VkPrimitiveTopology m_topology; 679 680 Move<VkImage> m_colorImage; 681 MovePtr<Allocation> m_colorImageAlloc; 682 Move<VkImageView> m_colorAttachment; 683 Move<VkBuffer> m_vertexBuffer; 684 MovePtr<Allocation> m_vertexBufferAlloc; 685 Move<VkShaderModule> m_vertexModule; 686 Move<VkShaderModule> m_fragmentModule; 687 Move<VkRenderPass> m_renderPass; 688 Move<VkFramebuffer> m_framebuffer; 689 Move<VkPipelineLayout> m_pipelineLayout; 690 Move<VkCommandPool> m_cmdPool; 691 Move<VkCommandBuffer> m_cmdBuffer; 692 693 // "deleted" 694 ScissorRenderer (const ScissorRenderer&); 695 ScissorRenderer& operator= (const ScissorRenderer&); 696}; 697 698tcu::TestStatus test (Context& context, const CaseDef caseDef) 699{ 700 const DeviceInterface& vk = context.getDeviceInterface(); 701 const VkDevice device = context.getDevice(); 702 Allocator& allocator = context.getDefaultAllocator(); 703 704 const IVec2 renderSize (128, 128); 705 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 706 const Vec4 scissorFullArea (0.0f, 0.0f, 1.0f, 1.0f); 707 const Vec4 primitiveColor (1.0f, 1.0f, 1.0f, 1.0f); 708 const Vec4 clearColor (0.5f, 0.5f, 1.0f, 1.0f); 709 710 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); 711 const Unique<VkBuffer> colorBufferFull (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT))); 712 const UniquePtr<Allocation> colorBufferFullAlloc (bindBuffer(vk, device, allocator, *colorBufferFull, MemoryRequirement::HostVisible)); 713 714 const Unique<VkBuffer> colorBufferScissored (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT))); 715 const UniquePtr<Allocation> colorBufferScissoredAlloc (bindBuffer(vk, device, allocator, *colorBufferScissored, MemoryRequirement::HostVisible)); 716 717 zeroBuffer(vk, device, *colorBufferFullAlloc, colorBufferSize); 718 zeroBuffer(vk, device, *colorBufferScissoredAlloc, colorBufferSize); 719 720 // Draw 721 { 722 const ScissorRenderer renderer (context, caseDef, renderSize, colorFormat, primitiveColor, clearColor); 723 724 renderer.draw(context, scissorFullArea, *colorBufferFull); 725 renderer.draw(context, caseDef.scissorArea, *colorBufferScissored); 726 } 727 728 // Log image 729 { 730 invalidateMappedMemoryRange(vk, device, colorBufferFullAlloc->getMemory(), 0ull, colorBufferSize); 731 invalidateMappedMemoryRange(vk, device, colorBufferScissoredAlloc->getMemory(), 0ull, colorBufferSize); 732 733 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferScissoredAlloc->getHostPtr()); 734 tcu::PixelBufferAccess referenceImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferFullAlloc->getHostPtr()); 735 736 // Apply scissor to the full image, so we can compare it with the result image. 737 applyScissor (referenceImage, caseDef.scissorArea, clearColor); 738 739 // Images should now match. 740 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage, resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT)) 741 return tcu::TestStatus::fail("Rendered image is not correct"); 742 } 743 744 return tcu::TestStatus::pass("OK"); 745} 746 747//! \note The ES 2.0 scissoring tests included color/depth/stencil clear cases, but these operations are not affected by scissor test in Vulkan. 748//! Scissor is part of the pipeline state and pipeline only affects the drawing commands. 749void createTestsInGroup (tcu::TestCaseGroup* scissorGroup) 750{ 751 tcu::TestContext& testCtx = scissorGroup->getTestContext(); 752 753 struct TestSpec 754 { 755 const char* name; 756 const char* description; 757 CaseDef caseDef; 758 }; 759 760 const Vec4 areaFull (0.0f, 0.0f, 1.0f, 1.0f); 761 const Vec4 areaCropped (0.2f, 0.2f, 0.6f, 0.6f); 762 const Vec4 areaCroppedMore (0.4f, 0.4f, 0.2f, 0.2f); 763 const Vec4 areaLeftHalf (0.0f, 0.0f, 0.5f, 1.0f); 764 const Vec4 areaRightHalf (0.5f, 0.0f, 0.5f, 1.0f); 765 766 // Points 767 { 768 MovePtr<tcu::TestCaseGroup> primitiveGroup (new tcu::TestCaseGroup(testCtx, "points", "")); 769 770 const TestSpec cases[] = 771 { 772 { "inside", "Points fully inside the scissor area", { areaFull, areaFull, TEST_PRIMITIVE_POINTS } }, 773 { "partially_inside", "Points partially inside the scissor area", { areaFull, areaCropped, TEST_PRIMITIVE_POINTS } }, 774 { "outside", "Points fully outside the scissor area", { areaLeftHalf, areaRightHalf, TEST_PRIMITIVE_POINTS } }, 775 }; 776 777 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i) 778 addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef); 779 780 scissorGroup->addChild(primitiveGroup.release()); 781 } 782 783 // Lines 784 { 785 MovePtr<tcu::TestCaseGroup> primitiveGroup (new tcu::TestCaseGroup(testCtx, "lines", "")); 786 787 const TestSpec cases[] = 788 { 789 { "inside", "Lines fully inside the scissor area", { areaFull, areaFull, TEST_PRIMITIVE_LINES } }, 790 { "partially_inside", "Lines partially inside the scissor area", { areaFull, areaCropped, TEST_PRIMITIVE_LINES } }, 791 { "outside", "Lines fully outside the scissor area", { areaLeftHalf, areaRightHalf, TEST_PRIMITIVE_LINES } }, 792 { "crossing", "A line crossing the scissor area", { areaFull, areaCroppedMore, TEST_PRIMITIVE_BIG_LINE } }, 793 }; 794 795 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i) 796 addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef); 797 798 scissorGroup->addChild(primitiveGroup.release()); 799 } 800 801 // Triangles 802 { 803 MovePtr<tcu::TestCaseGroup> primitiveGroup (new tcu::TestCaseGroup(testCtx, "triangles", "")); 804 805 const TestSpec cases[] = 806 { 807 { "inside", "Triangles fully inside the scissor area", { areaFull, areaFull, TEST_PRIMITIVE_TRIANGLES } }, 808 { "partially_inside", "Triangles partially inside the scissor area", { areaFull, areaCropped, TEST_PRIMITIVE_TRIANGLES } }, 809 { "outside", "Triangles fully outside the scissor area", { areaLeftHalf, areaRightHalf, TEST_PRIMITIVE_TRIANGLES } }, 810 { "crossing", "A triangle crossing the scissor area", { areaFull, areaCroppedMore, TEST_PRIMITIVE_BIG_TRIANGLE } }, 811 }; 812 813 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i) 814 addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef); 815 816 scissorGroup->addChild(primitiveGroup.release()); 817 } 818 819 // Mulit-viewport scissor 820 { 821 scissorGroup->addChild(createScissorMultiViewportTests(testCtx)); 822 } 823} 824 825} // anonymous 826 827tcu::TestCaseGroup* createScissorTests (tcu::TestContext& testCtx) 828{ 829 return createTestGroup(testCtx, "scissor", "Scissor tests", createTestsInGroup); 830} 831 832} // FragmentOperations 833} // vkt 834